mirror of
https://github.com/lnbits/lnbits.git
synced 2025-05-30 01:29:30 +02:00
chore: code clean-up
This commit is contained in:
parent
2044c9f14b
commit
5ffc7185e8
@ -59,7 +59,7 @@ class TokenBucket:
|
||||
# Calculate time needed for one token
|
||||
wait_time = (self.period / self.rate) * (1 - self.tokens)
|
||||
await asyncio.sleep(wait_time)
|
||||
|
||||
|
||||
# After waiting, update time and add one token
|
||||
self.last_refill = time.monotonic()
|
||||
self.tokens = 1 # We now have exactly one token available
|
||||
@ -132,7 +132,7 @@ class StrikeWallet(Wallet):
|
||||
try:
|
||||
await self.client.aclose()
|
||||
except Exception:
|
||||
logger.exception("Error closing Strike client")
|
||||
logger.error("Error closing Strike client")
|
||||
|
||||
# --------------------------------------------------------------------- #
|
||||
# low-level request helpers #
|
||||
@ -246,7 +246,7 @@ class StrikeWallet(Wallet):
|
||||
logger.error(f"Strike API error: {e.response.text}")
|
||||
return StatusResponse(f"Strike API error: {e.response.text}", 0)
|
||||
except Exception:
|
||||
logger.exception("Unexpected error in status()")
|
||||
logger.error("Unexpected error in status()")
|
||||
return StatusResponse("Connection error", 0)
|
||||
|
||||
async def create_invoice(
|
||||
@ -266,7 +266,7 @@ class StrikeWallet(Wallet):
|
||||
"amount": {
|
||||
"currency": "BTC",
|
||||
"amount": str(btc_amt),
|
||||
}, # Set amount in BTC.
|
||||
},
|
||||
"description": memo or "",
|
||||
},
|
||||
"targetCurrency": "BTC",
|
||||
@ -291,12 +291,13 @@ class StrikeWallet(Wallet):
|
||||
ok=True, checking_id=invoice_id, payment_request=bolt11
|
||||
)
|
||||
except httpx.HTTPStatusError as e:
|
||||
logger.error(e)
|
||||
msg = e.response.json().get(
|
||||
"message", e.response.text
|
||||
) # Get error message from response.
|
||||
return InvoiceResponse(ok=False, error_message=f"Strike API error: {msg}")
|
||||
except Exception:
|
||||
logger.exception("Error in create_invoice()")
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return InvoiceResponse(ok=False, error_message="Connection error")
|
||||
|
||||
async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse:
|
||||
@ -306,148 +307,121 @@ class StrikeWallet(Wallet):
|
||||
"/payment-quotes/lightning",
|
||||
json={"lnInvoice": bolt11},
|
||||
)
|
||||
quote_id = q.json().get("paymentQuoteId") # Get the payment quote ID.
|
||||
if not quote_id: # Check if the quote ID is present.
|
||||
quote_id = q.json().get("paymentQuoteId")
|
||||
if not quote_id:
|
||||
return PaymentResponse(
|
||||
False, None, None, None, "Strike: missing paymentQuoteId"
|
||||
ok=False, error_message="Strike: missing paymentQuoteId"
|
||||
)
|
||||
|
||||
# 2) Execute the payment quote.
|
||||
e = await self._patch(f"/payment-quotes/{quote_id}/execute")
|
||||
data = (
|
||||
e.json() if e.content else {}
|
||||
) # Parse JSON response or use an empty dictionary.
|
||||
payment_id = data.get("paymentId") # Get the payment ID.
|
||||
state = data.get(
|
||||
"state", ""
|
||||
).upper() # Get the payment state and convert it to uppercase.
|
||||
data = e.json() if e.content else {}
|
||||
payment_id = data.get("paymentId")
|
||||
state = data.get("state", "").upper()
|
||||
|
||||
# Network fee → msat.
|
||||
fee_obj = (
|
||||
data.get("lightningNetworkFee") or data.get("totalFee") or {}
|
||||
) # Get fee object.
|
||||
fee_btc = Decimal(fee_obj.get("amount", "0")) # Get fee amount in BTC.
|
||||
fee_msat = int(
|
||||
fee_btc * Decimal(1e11)
|
||||
) # Convert fee from BTC to millisatoshis.
|
||||
fee_obj = data.get("lightningNetworkFee") or data.get("totalFee") or {}
|
||||
fee_btc = Decimal(fee_obj.get("amount", "0"))
|
||||
fee_msat = int(fee_btc * Decimal(1e11)) # millisatoshis.
|
||||
|
||||
# Store mapping for later polling.
|
||||
if payment_id: # If payment ID is present.
|
||||
self.pending_payments[payment_id] = quote_id
|
||||
|
||||
if state in {"SUCCEEDED", "COMPLETED"}: # If payment succeeded.
|
||||
preimage = data.get("preimage") or data.get(
|
||||
"preImage"
|
||||
) # Get payment preimage.
|
||||
if state in {"SUCCEEDED", "COMPLETED"}:
|
||||
preimage = data.get("preimage") or data.get("preImage")
|
||||
return PaymentResponse(
|
||||
True, payment_id, fee_msat, preimage, None
|
||||
) # Return successful payment response.
|
||||
ok=True,
|
||||
checking_id=payment_id,
|
||||
fee_msat=fee_msat,
|
||||
preimage=preimage,
|
||||
)
|
||||
|
||||
# Explicitly check for known failure states.
|
||||
failed_states = {
|
||||
"CANCELED",
|
||||
"FAILED",
|
||||
"TIMED_OUT",
|
||||
} # Add any other known failure states here.
|
||||
}
|
||||
if state in failed_states:
|
||||
return PaymentResponse(
|
||||
False, payment_id, None, None, f"State: {state}"
|
||||
) # Return failed payment response with state.
|
||||
ok=False, checking_id=payment_id, error_message=f"State: {state}"
|
||||
)
|
||||
|
||||
# Treat all other states as pending (including unknown states).
|
||||
return PaymentResponse(
|
||||
None, payment_id, None, None, None
|
||||
) # Return pending payment response.
|
||||
return PaymentResponse(ok=None, checking_id=payment_id)
|
||||
|
||||
except httpx.HTTPStatusError as e:
|
||||
error_message = e.response.json().get(
|
||||
"message", e.response.text
|
||||
) # Get error message from response.
|
||||
error_message = e.response.json().get("message", e.response.text)
|
||||
# Keep pending. Not sure if the payment went trough or not.
|
||||
return PaymentResponse(
|
||||
ok=False,
|
||||
checking_id=None,
|
||||
fee_msat=None,
|
||||
preimage=None,
|
||||
ok=None,
|
||||
error_message=f"Strike API error: {error_message}",
|
||||
) # Return payment response with error.
|
||||
except Exception:
|
||||
logger.exception("Error in pay_invoice()")
|
||||
return PaymentResponse(False, None, None, None, "Connection error")
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
# Keep pending. Not sure if the payment went trough or not.
|
||||
return PaymentResponse(ok=None, error_message="Connection error")
|
||||
|
||||
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
||||
try:
|
||||
r = await self._get(
|
||||
f"/receive-requests/{checking_id}/receives"
|
||||
) # Get receive requests for the invoice.
|
||||
for itm in r.json().get("items", []): # Iterate through received items.
|
||||
if itm.get("state") == "COMPLETED": # If an item is completed.
|
||||
r = await self._get(f"/receive-requests/{checking_id}/receives")
|
||||
for itm in r.json().get("items", []):
|
||||
if itm.get("state") == "COMPLETED":
|
||||
# Extract preimage from lightning object if available
|
||||
preimage = None
|
||||
lightning_data = itm.get("lightning")
|
||||
if lightning_data:
|
||||
preimage = lightning_data.get("preimage")
|
||||
return PaymentSuccessStatus(
|
||||
fee_msat=0, preimage=preimage
|
||||
) # Return successful payment status with preimage.
|
||||
return (
|
||||
PaymentPendingStatus()
|
||||
) # Return pending payment status if no completed items.
|
||||
return PaymentSuccessStatus(fee_msat=0, preimage=preimage)
|
||||
return PaymentPendingStatus()
|
||||
|
||||
except httpx.HTTPStatusError as e:
|
||||
if e.response.status_code == 404: # If invoice not found.
|
||||
try:
|
||||
r2 = await self._get(
|
||||
f"/v1/invoices/{checking_id}"
|
||||
) # Try getting invoice from the old endpoint with correct path.
|
||||
st = r2.json().get("state", "") # Get invoice state.
|
||||
if st == "PAID": # If invoice is paid.
|
||||
return PaymentSuccessStatus(
|
||||
fee_msat=0
|
||||
) # Return successful payment status.
|
||||
if st == "CANCELLED": # If invoice is cancelled.
|
||||
return PaymentStatus(False) # Return failed payment status.
|
||||
# Try getting invoice from the old endpoint with correct path.
|
||||
r2 = await self._get(f"/v1/invoices/{checking_id}")
|
||||
st = r2.json().get("state", "")
|
||||
if st == "PAID":
|
||||
return PaymentSuccessStatus(fee_msat=0)
|
||||
if st == "CANCELLED":
|
||||
return PaymentFailedStatus(False)
|
||||
except Exception:
|
||||
pass # Ignore exceptions from the old endpoint.
|
||||
return PaymentPendingStatus() # Return pending payment status.
|
||||
except Exception: # Handle other exceptions.
|
||||
logger.exception("Error in get_invoice_status()")
|
||||
return PaymentPendingStatus()
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return PaymentPendingStatus()
|
||||
|
||||
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
||||
quote_id = self.pending_payments.get(checking_id)
|
||||
if not quote_id: # Payment not found in pending list.
|
||||
if not quote_id:
|
||||
if checking_id in self.failed_payments:
|
||||
return PaymentFailedStatus(
|
||||
paid=False
|
||||
) # Payment is known to have failed.
|
||||
return PaymentFailedStatus()
|
||||
return PaymentPendingStatus()
|
||||
try: # Try to get payment quote.
|
||||
r = await self._get(
|
||||
f"/payment-quotes/{quote_id}"
|
||||
) # Get payment quote from Strike API.
|
||||
try:
|
||||
r = await self._get(f"/payment-quotes/{quote_id}")
|
||||
r.raise_for_status()
|
||||
data = r.json() # Parse JSON response.
|
||||
state = data.get("state") # Get payment state.
|
||||
preimage = data.get("preimage") or data.get(
|
||||
"preImage"
|
||||
) # Get payment preimage.
|
||||
if state in ("SUCCEEDED", "COMPLETED"): # If payment succeeded.
|
||||
return PaymentSuccessStatus(
|
||||
fee_msat=0, preimage=preimage
|
||||
) # Return successful payment status.
|
||||
if state == "FAILED": # Explicitly check for FAILED state
|
||||
return PaymentStatus(False) # Return failed payment status.
|
||||
# Default to pending for PENDING and any other states
|
||||
return PaymentPendingStatus() # Return pending payment status.
|
||||
data = r.json()
|
||||
state = data.get("state")
|
||||
preimage = data.get("preimage") or data.get("preImage")
|
||||
if state in {"SUCCEEDED", "COMPLETED"}:
|
||||
return PaymentSuccessStatus(fee_msat=0, preimage=preimage)
|
||||
# todo: check for FAILED status and default to pending
|
||||
if state == "FAILED":
|
||||
return PaymentFailedStatus()
|
||||
return PaymentPendingStatus()
|
||||
except httpx.HTTPStatusError as e:
|
||||
# todo: better handle this inside the try block
|
||||
# todo: right before r.raise_for_status()
|
||||
if e.response.status_code == 404:
|
||||
# Quote not found, likely expired or payment failed.
|
||||
self.pending_payments.pop(checking_id, None)
|
||||
self.failed_payments[checking_id] = quote_id
|
||||
return PaymentFailedStatus(paid=False)
|
||||
return PaymentFailedStatus()
|
||||
raise # Re-raise other HTTP errors
|
||||
except Exception: # Handle exceptions.
|
||||
logger.exception(f"Error in get_payment_status() for payment {checking_id}")
|
||||
return PaymentPendingStatus() # Treat as pending for now.
|
||||
except Exception as e: # Handle exceptions.
|
||||
logger.error(e)
|
||||
return PaymentPendingStatus()
|
||||
|
||||
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
|
||||
"""
|
||||
@ -526,5 +500,5 @@ class StrikeWallet(Wallet):
|
||||
) # Get invoices from Strike API.
|
||||
return r.json()
|
||||
except Exception:
|
||||
logger.exception("Error in get_invoices()")
|
||||
logger.error("Error in get_invoices()")
|
||||
return {"error": "unable to fetch invoices"}
|
||||
|
Loading…
x
Reference in New Issue
Block a user