Merge branch 'main' into FinalAdminUI

This commit is contained in:
Vlad Stan
2022-12-12 10:49:31 +02:00
committed by GitHub
10 changed files with 139 additions and 47 deletions
+15 -30
View File
@@ -338,37 +338,14 @@ async def delete_expired_invoices(
AND time < {db.timestamp_now} - {db.interval_seconds(2592000)}
"""
)
# then we delete all expired invoices, checking one by one
rows = await (conn or db).fetchall(
# then we delete all invoices whose expiry date is in the past
await (conn or db).execute(
f"""
SELECT bolt11
FROM apipayments
WHERE pending = true
AND bolt11 IS NOT NULL
AND amount > 0 AND time < {db.timestamp_now} - {db.interval_seconds(86400)}
DELETE FROM apipayments
WHERE pending = true AND amount > 0
AND expiry < {db.timestamp_now}
"""
)
logger.debug(f"Checking expiry of {len(rows)} invoices")
for i, (payment_request,) in enumerate(rows):
try:
invoice = bolt11.decode(payment_request)
except:
continue
expiration_date = datetime.datetime.fromtimestamp(invoice.date + invoice.expiry)
if expiration_date > datetime.datetime.utcnow():
continue
logger.debug(
f"Deleting expired invoice {i}/{len(rows)}: {invoice.payment_hash} (expired: {expiration_date})"
)
await (conn or db).execute(
"""
DELETE FROM apipayments
WHERE pending = true AND hash = ?
""",
(invoice.payment_hash,),
)
# payments
@@ -395,12 +372,19 @@ async def create_payment(
# previous_payment = await get_wallet_payment(wallet_id, payment_hash, conn=conn)
# assert previous_payment is None, "Payment already exists"
try:
invoice = bolt11.decode(payment_request)
expiration_date = datetime.datetime.fromtimestamp(invoice.date + invoice.expiry)
except:
# assume maximum bolt11 expiry of 31 days to be on the safe side
expiration_date = datetime.datetime.now() + datetime.timedelta(days=31)
await (conn or db).execute(
"""
INSERT INTO apipayments
(wallet, checking_id, bolt11, hash, preimage,
amount, pending, memo, fee, extra, webhook)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
amount, pending, memo, fee, extra, webhook, expiry)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
wallet_id,
@@ -416,6 +400,7 @@ async def create_payment(
if extra and extra != {} and type(extra) is dict
else None,
webhook,
db.datetime_to_timestamp(expiration_date),
),
)
+70 -1
View File
@@ -1,5 +1,10 @@
import datetime
from loguru import logger
from sqlalchemy.exc import OperationalError # type: ignore
from lnbits import bolt11
async def m000_create_migrations_table(db):
await db.execute(
@@ -190,7 +195,71 @@ async def m005_balance_check_balance_notify(db):
)
async def m006_create_admin_settings_table(db):
async def m006_add_invoice_expiry_to_apipayments(db):
"""
Adds invoice expiry column to apipayments.
"""
try:
await db.execute("ALTER TABLE apipayments ADD COLUMN expiry TIMESTAMP")
except OperationalError:
pass
async def m007_set_invoice_expiries(db):
"""
Precomputes invoice expiry for existing pending incoming payments.
"""
try:
rows = await (
await db.execute(
f"""
SELECT bolt11, checking_id
FROM apipayments
WHERE pending = true
AND amount > 0
AND bolt11 IS NOT NULL
AND expiry IS NULL
AND time < {db.timestamp_now}
"""
)
).fetchall()
if len(rows):
logger.info(f"Mirgraion: Checking expiry of {len(rows)} invoices")
for i, (
payment_request,
checking_id,
) in enumerate(rows):
try:
invoice = bolt11.decode(payment_request)
if invoice.expiry is None:
continue
expiration_date = datetime.datetime.fromtimestamp(
invoice.date + invoice.expiry
)
logger.info(
f"Mirgraion: {i+1}/{len(rows)} setting expiry of invoice {invoice.payment_hash} to {expiration_date}"
)
await db.execute(
"""
UPDATE apipayments SET expiry = ?
WHERE checking_id = ? AND amount > 0
""",
(
db.datetime_to_timestamp(expiration_date),
checking_id,
),
)
except:
continue
except OperationalError:
# this is necessary now because it may be the case that this migration will
# run twice in some environments.
# catching errors like this won't be necessary in anymore now that we
# keep track of db versions so no migration ever runs twice.
pass
async def m008_create_admin_settings_table(db):
await db.execute(
"""
CREATE TABLE IF NOT EXISTS settings (
+15 -1
View File
@@ -1,6 +1,8 @@
import datetime
import hashlib
import hmac
import json
import time
from sqlite3 import Row
from typing import Dict, List, NamedTuple, Optional
@@ -85,6 +87,7 @@ class Payment(BaseModel):
bolt11: str
preimage: str
payment_hash: str
expiry: Optional[float]
extra: Optional[Dict] = {}
wallet_id: str
webhook: Optional[str]
@@ -103,6 +106,7 @@ class Payment(BaseModel):
fee=row["fee"],
memo=row["memo"],
time=row["time"],
expiry=row["expiry"],
wallet_id=row["wallet"],
webhook=row["webhook"],
webhook_status=row["webhook_status"],
@@ -130,6 +134,10 @@ class Payment(BaseModel):
def is_out(self) -> bool:
return self.amount < 0
@property
def is_expired(self) -> bool:
return self.expiry < time.time() if self.expiry else False
@property
def is_uncheckable(self) -> bool:
return self.checking_id.startswith("internal_")
@@ -173,7 +181,13 @@ class Payment(BaseModel):
logger.debug(f"Status: {status}")
if self.is_out and status.failed:
if self.is_in and status.pending and self.is_expired and self.expiry:
expiration_date = datetime.datetime.fromtimestamp(self.expiry)
logger.debug(
f"Deleting expired incoming pending payment {self.checking_id}: expired {expiration_date}"
)
await self.delete(conn)
elif self.is_out and status.failed:
logger.warning(
f"Deleting outgoing failed payment {self.checking_id}: {status}"
)