fix: update API response structure and fix checking_id mismatch (#3478)
Co-authored-by: Vlad Stan <stan.v.vlad@gmail.com>
This commit is contained in:
parent
cf7726ddfd
commit
c84d1b66c6
1 changed files with 254 additions and 127 deletions
|
|
@ -7,6 +7,7 @@ from decimal import Decimal
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
from bolt11 import decode as bolt11_decode
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from lnbits.helpers import normalize_endpoint
|
from lnbits.helpers import normalize_endpoint
|
||||||
|
|
@ -131,53 +132,12 @@ class StrikeWallet(Wallet):
|
||||||
self._cached_balance_ts: float = 0.0
|
self._cached_balance_ts: float = 0.0
|
||||||
self._cache_ttl = 30 # seconds
|
self._cache_ttl = 30 # seconds
|
||||||
|
|
||||||
def _persist_pending(self):
|
|
||||||
try:
|
|
||||||
with open(self.state_path, "w") as f:
|
|
||||||
json.dump(self.pending_invoices, f)
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"Could not persist pending invoices: {e}")
|
|
||||||
|
|
||||||
async def cleanup(self) -> None:
|
async def cleanup(self) -> None:
|
||||||
try:
|
try:
|
||||||
await self.client.aclose()
|
await self.client.aclose()
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.warning("Error closing Strike client")
|
logger.warning("Error closing Strike client")
|
||||||
|
|
||||||
# --------------------------------------------------------------------- #
|
|
||||||
# low-level request helpers #
|
|
||||||
# --------------------------------------------------------------------- #
|
|
||||||
|
|
||||||
async def _req(self, method: str, path: str, /, **kw) -> httpx.Response:
|
|
||||||
"""Make a Strike HTTP call with:
|
|
||||||
One Strike HTTP call with
|
|
||||||
• rate limiting based on endpoint type
|
|
||||||
• concurrency throttle
|
|
||||||
• exponential back-off + jitter
|
|
||||||
• explicit retry on 429/5xx
|
|
||||||
• latency logging
|
|
||||||
"""
|
|
||||||
# Apply the appropriate rate limiter based on the endpoint path.
|
|
||||||
if path.startswith("/invoices") or path.startswith("/receive-requests"):
|
|
||||||
await self._invoice_limiter.consume()
|
|
||||||
elif path.startswith("/payment-quotes"):
|
|
||||||
await self._payment_limiter.consume()
|
|
||||||
else:
|
|
||||||
await self._general_limiter.consume()
|
|
||||||
|
|
||||||
async with self._sem:
|
|
||||||
return await self.client.request(method, path, **kw)
|
|
||||||
|
|
||||||
# Typed wrappers - so call-sites stay tidy.
|
|
||||||
async def _get(self, path: str, **kw) -> httpx.Response: # GET request.
|
|
||||||
return await self._req("GET", path, **kw)
|
|
||||||
|
|
||||||
async def _post(self, path: str, **kw) -> httpx.Response:
|
|
||||||
return await self._req("POST", path, **kw)
|
|
||||||
|
|
||||||
async def _patch(self, path: str, **kw) -> httpx.Response:
|
|
||||||
return await self._req("PATCH", path, **kw)
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------- #
|
# --------------------------------------------------------------------- #
|
||||||
# LNbits wallet API implementation #
|
# LNbits wallet API implementation #
|
||||||
# --------------------------------------------------------------------- #
|
# --------------------------------------------------------------------- #
|
||||||
|
|
@ -266,63 +226,75 @@ class StrikeWallet(Wallet):
|
||||||
return InvoiceResponse(ok=False, error_message="Connection error")
|
return InvoiceResponse(ok=False, error_message="Connection error")
|
||||||
|
|
||||||
async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse:
|
async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse:
|
||||||
|
# Extract payment hash from invoice for checking_id
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 1) Create a payment quote.
|
invoice = bolt11_decode(bolt11)
|
||||||
q = await self._post(
|
payment_hash = invoice.payment_hash
|
||||||
"/payment-quotes/lightning",
|
except Exception as decode_exc:
|
||||||
json={"lnInvoice": bolt11},
|
logger.warning(f"Strike: Failed to decode invoice: {decode_exc}")
|
||||||
|
return PaymentResponse(
|
||||||
|
ok=False, error_message=f"Invalid invoice: {decode_exc!s}"
|
||||||
)
|
)
|
||||||
q.raise_for_status()
|
|
||||||
quote_id = q.json().get("paymentQuoteId")
|
|
||||||
if not quote_id:
|
|
||||||
return PaymentResponse(
|
|
||||||
ok=False, error_message="Strike: missing payment quote Id"
|
|
||||||
)
|
|
||||||
|
|
||||||
# 2) Execute the payment quote.
|
try:
|
||||||
e = await self._patch(f"/payment-quotes/{quote_id}/execute")
|
# 1) Create a payment quote
|
||||||
e.raise_for_status()
|
quote_id, error = await self._create_payment_quote(bolt11)
|
||||||
|
if error or not quote_id:
|
||||||
|
return PaymentResponse(ok=False, error_message=error or "Unknown error")
|
||||||
|
|
||||||
|
# 2) Execute the payment quote
|
||||||
|
data, error = await self._execute_payment_quote(quote_id)
|
||||||
|
if error or not data:
|
||||||
|
return PaymentResponse(ok=False, error_message=error or "Unknown error")
|
||||||
|
|
||||||
data = e.json() if e.content else {}
|
|
||||||
payment_id = data.get("paymentId")
|
|
||||||
state = data.get("state", "").upper()
|
state = data.get("state", "").upper()
|
||||||
|
payment_id = data.get("paymentId")
|
||||||
|
|
||||||
# Network fee → msat.
|
# Parse fee
|
||||||
fee_obj = data.get("lightningNetworkFee") or data.get("totalFee") or {}
|
fee_msat = self._parse_payment_fee(data, payment_id or "")
|
||||||
fee_btc = Decimal(fee_obj.get("amount", "0"))
|
|
||||||
fee_msat = int(fee_btc * Decimal("1e11")) # millisatoshis.
|
|
||||||
|
|
||||||
|
# Handle successful payment
|
||||||
if state in {"SUCCEEDED", "COMPLETED"}:
|
if state in {"SUCCEEDED", "COMPLETED"}:
|
||||||
preimage = data.get("preimage") or data.get("preImage")
|
preimage = self._extract_preimage(data)
|
||||||
return PaymentResponse(
|
return PaymentResponse(
|
||||||
ok=True,
|
ok=True,
|
||||||
checking_id=payment_id,
|
checking_id=payment_hash,
|
||||||
fee_msat=fee_msat,
|
fee_msat=fee_msat,
|
||||||
preimage=preimage,
|
preimage=preimage,
|
||||||
)
|
)
|
||||||
|
|
||||||
failed_states = {
|
# Handle failed payment
|
||||||
"CANCELED",
|
failed_states = {"CANCELED", "FAILED", "TIMED_OUT"}
|
||||||
"FAILED",
|
|
||||||
"TIMED_OUT",
|
|
||||||
}
|
|
||||||
if state in failed_states:
|
if state in failed_states:
|
||||||
|
logger.warning(
|
||||||
|
f"Strike payment {payment_id} failed with state: {state}"
|
||||||
|
)
|
||||||
return PaymentResponse(
|
return PaymentResponse(
|
||||||
ok=False, checking_id=payment_id, error_message=f"State: {state}"
|
ok=False,
|
||||||
|
checking_id=payment_hash,
|
||||||
|
error_message=f"Payment {state.lower()}",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Store mapping for later polling.
|
# Store mapping for later polling
|
||||||
if payment_id:
|
self.pending_payments[payment_hash] = quote_id
|
||||||
# todo: this will be lost on server restart
|
|
||||||
self.pending_payments[payment_id] = quote_id
|
|
||||||
|
|
||||||
# Treat all other states as pending (including unknown states).
|
# Treat all other states as pending
|
||||||
return PaymentResponse(ok=None, checking_id=payment_id)
|
return PaymentResponse(ok=None, checking_id=payment_hash)
|
||||||
|
|
||||||
|
except httpx.HTTPStatusError as http_exc:
|
||||||
|
logger.warning(f"Strike HTTP error during payment: {http_exc}")
|
||||||
|
logger.warning(
|
||||||
|
f"Response status: {http_exc.response.status_code}, "
|
||||||
|
f"body: {http_exc.response.text}"
|
||||||
|
)
|
||||||
|
return PaymentResponse(
|
||||||
|
ok=False,
|
||||||
|
error_message=f"Strike API error: {http_exc.response.status_code}",
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(e)
|
logger.warning(f"Strike payment exception: {e}", exc_info=True)
|
||||||
# Keep pending. Not sure if the payment went trough or not.
|
return PaymentResponse(ok=None, error_message=f"Error: {e!s}")
|
||||||
return PaymentResponse(ok=None, error_message="Connection error")
|
|
||||||
|
|
||||||
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
|
||||||
try:
|
try:
|
||||||
|
|
@ -390,26 +362,31 @@ class StrikeWallet(Wallet):
|
||||||
logger.debug(f"Error while fetching payment {checking_id}.")
|
logger.debug(f"Error while fetching payment {checking_id}.")
|
||||||
return PaymentPendingStatus()
|
return PaymentPendingStatus()
|
||||||
|
|
||||||
async def _get_invoices_status_batch(
|
async def get_invoices(
|
||||||
self, invoice_ids: list[str]
|
self,
|
||||||
) -> dict[str, PaymentStatus]:
|
filters: str | None = None,
|
||||||
out: dict[str, PaymentStatus] = {}
|
orderby: str | None = None,
|
||||||
if not invoice_ids:
|
skip: int | None = None,
|
||||||
return out
|
top: int | None = None,
|
||||||
ids_list = ",".join(f"'{i}'" for i in invoice_ids)
|
) -> dict[str, Any]:
|
||||||
filter_expr = f"receiveRequestId in ({ids_list})"
|
try:
|
||||||
params = {"$filter": filter_expr, "$top": len(invoice_ids)}
|
params: dict[str, Any] = {}
|
||||||
r = await self._get("/receive-requests/receives", params=params)
|
if filters:
|
||||||
r.raise_for_status()
|
params["$filter"] = filters
|
||||||
items = r.json().get("items") or r.json().get("value") or []
|
if orderby:
|
||||||
completed = {item.get("receiveRequestId") for item in items}
|
params["$orderby"] = orderby
|
||||||
for inv in invoice_ids:
|
if skip is not None:
|
||||||
out[inv] = (
|
params["$skip"] = skip
|
||||||
PaymentSuccessStatus(fee_msat=0)
|
if top is not None:
|
||||||
if inv in completed
|
params["$top"] = top
|
||||||
else PaymentPendingStatus()
|
r = await self._get(
|
||||||
)
|
"/invoices", params=params
|
||||||
return out
|
) # Get invoices from Strike API.
|
||||||
|
r.raise_for_status()
|
||||||
|
return r.json()
|
||||||
|
except Exception:
|
||||||
|
logger.warning("Error in get_invoices()")
|
||||||
|
return {"error": "unable to fetch invoices"}
|
||||||
|
|
||||||
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
|
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
|
||||||
"""
|
"""
|
||||||
|
|
@ -457,36 +434,155 @@ class StrikeWallet(Wallet):
|
||||||
min_sleep_for_rate = processed * 60 / rate_limit - elapsed
|
min_sleep_for_rate = processed * 60 / rate_limit - elapsed
|
||||||
await asyncio.sleep(max(sleep_s, min_sleep_for_rate, 0))
|
await asyncio.sleep(max(sleep_s, min_sleep_for_rate, 0))
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
# low-level request helpers #
|
||||||
|
# --------------------------------------------------------------------- #
|
||||||
|
|
||||||
|
def _persist_pending(self):
|
||||||
|
try:
|
||||||
|
with open(self.state_path, "w") as f:
|
||||||
|
json.dump(self.pending_invoices, f)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Could not persist pending invoices: {e}")
|
||||||
|
|
||||||
|
async def _req(self, method: str, path: str, /, **kw) -> httpx.Response:
|
||||||
|
"""Make a Strike HTTP call with:
|
||||||
|
One Strike HTTP call with
|
||||||
|
• rate limiting based on endpoint type
|
||||||
|
• concurrency throttle
|
||||||
|
• exponential back-off + jitter
|
||||||
|
• explicit retry on 429/5xx
|
||||||
|
• latency logging
|
||||||
|
"""
|
||||||
|
# Apply the appropriate rate limiter based on the endpoint path.
|
||||||
|
if path.startswith("/invoices") or path.startswith("/receive-requests"):
|
||||||
|
await self._invoice_limiter.consume()
|
||||||
|
elif path.startswith("/payment-quotes"):
|
||||||
|
await self._payment_limiter.consume()
|
||||||
|
else:
|
||||||
|
await self._general_limiter.consume()
|
||||||
|
|
||||||
|
async with self._sem:
|
||||||
|
return await self.client.request(method, path, **kw)
|
||||||
|
|
||||||
|
# Typed wrappers - so call-sites stay tidy.
|
||||||
|
async def _get(self, path: str, **kw) -> httpx.Response: # GET request.
|
||||||
|
return await self._req("GET", path, **kw)
|
||||||
|
|
||||||
|
async def _post(self, path: str, **kw) -> httpx.Response:
|
||||||
|
return await self._req("POST", path, **kw)
|
||||||
|
|
||||||
|
async def _patch(self, path: str, **kw) -> httpx.Response:
|
||||||
|
return await self._req("PATCH", path, **kw)
|
||||||
|
|
||||||
|
async def _create_payment_quote(self, bolt11: str) -> tuple[str | None, str | None]:
|
||||||
|
"""Create a payment quote and return (quote_id, error_message)."""
|
||||||
|
try:
|
||||||
|
q = await self._post(
|
||||||
|
"/payment-quotes/lightning",
|
||||||
|
json={"lnInvoice": bolt11},
|
||||||
|
)
|
||||||
|
q.raise_for_status()
|
||||||
|
except httpx.HTTPStatusError as quote_exc:
|
||||||
|
logger.warning(f"Strike: Failed to create payment quote: {quote_exc}")
|
||||||
|
logger.warning(
|
||||||
|
f"Response: {quote_exc.response.status_code} - "
|
||||||
|
f"{quote_exc.response.text}"
|
||||||
|
)
|
||||||
|
error_msg = (
|
||||||
|
f"Strike: Failed to create quote "
|
||||||
|
f"(HTTP {quote_exc.response.status_code})"
|
||||||
|
)
|
||||||
|
return None, error_msg
|
||||||
|
|
||||||
|
quote_data = q.json()
|
||||||
|
quote_id = quote_data.get("paymentQuoteId")
|
||||||
|
if not quote_id:
|
||||||
|
logger.warning(
|
||||||
|
f"Strike: missing paymentQuoteId in quote response: {quote_data}"
|
||||||
|
)
|
||||||
|
return None, "Strike: missing payment quote Id"
|
||||||
|
|
||||||
|
return quote_id, None
|
||||||
|
|
||||||
|
async def _execute_payment_quote(
|
||||||
|
self, quote_id: str
|
||||||
|
) -> tuple[dict | None, str | None]:
|
||||||
|
"""Execute a payment quote and return (response_data, error_message)."""
|
||||||
|
try:
|
||||||
|
e = await self._patch(f"/payment-quotes/{quote_id}/execute")
|
||||||
|
e.raise_for_status()
|
||||||
|
except httpx.HTTPStatusError as exec_exc:
|
||||||
|
logger.warning(
|
||||||
|
f"Strike: Failed to execute payment quote {quote_id}: {exec_exc}"
|
||||||
|
)
|
||||||
|
logger.warning(
|
||||||
|
f"Response: {exec_exc.response.status_code} - "
|
||||||
|
f"{exec_exc.response.text}"
|
||||||
|
)
|
||||||
|
error_msg = (
|
||||||
|
f"Strike: Failed to execute quote "
|
||||||
|
f"(HTTP {exec_exc.response.status_code})"
|
||||||
|
)
|
||||||
|
return None, error_msg
|
||||||
|
|
||||||
|
data = e.json() if e.content else {}
|
||||||
|
payment_id = data.get("paymentId")
|
||||||
|
if not payment_id:
|
||||||
|
logger.warning(f"Strike: missing paymentId in response: {data}")
|
||||||
|
return None, "Strike: missing paymentId in response"
|
||||||
|
|
||||||
|
return data, None
|
||||||
|
|
||||||
|
def _parse_payment_fee(self, data: dict, payment_id: str) -> int:
|
||||||
|
"""Parse payment fee from response data and return fee in millisatoshis."""
|
||||||
|
lightning_data = data.get("lightning", {})
|
||||||
|
fee_obj = lightning_data.get("networkFee") or data.get("totalFee") or {}
|
||||||
|
fee_msat = 0
|
||||||
|
try:
|
||||||
|
fee_amount = fee_obj.get("amount")
|
||||||
|
if fee_amount is not None:
|
||||||
|
fee_btc = Decimal(str(fee_amount))
|
||||||
|
fee_msat = int(fee_btc * Decimal("1e11"))
|
||||||
|
except Exception as fee_exc:
|
||||||
|
logger.warning(f"Error parsing fee for payment {payment_id}: {fee_exc}")
|
||||||
|
return fee_msat
|
||||||
|
|
||||||
|
def _extract_preimage(self, data: dict) -> str | None:
|
||||||
|
"""Extract preimage from payment response data."""
|
||||||
|
lightning_data = data.get("lightning", {})
|
||||||
|
return (
|
||||||
|
lightning_data.get("preimage")
|
||||||
|
or lightning_data.get("preImage")
|
||||||
|
or data.get("preimage")
|
||||||
|
or data.get("preImage")
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _get_invoices_status_batch(
|
||||||
|
self, invoice_ids: list[str]
|
||||||
|
) -> dict[str, PaymentStatus]:
|
||||||
|
out: dict[str, PaymentStatus] = {}
|
||||||
|
if not invoice_ids:
|
||||||
|
return out
|
||||||
|
ids_list = ",".join(f"'{i}'" for i in invoice_ids)
|
||||||
|
filter_expr = f"receiveRequestId in ({ids_list})"
|
||||||
|
params = {"$filter": filter_expr, "$top": len(invoice_ids)}
|
||||||
|
r = await self._get("/receive-requests/receives", params=params)
|
||||||
|
r.raise_for_status()
|
||||||
|
items = r.json().get("items") or r.json().get("value") or []
|
||||||
|
completed = {item.get("receiveRequestId") for item in items}
|
||||||
|
for inv in invoice_ids:
|
||||||
|
out[inv] = (
|
||||||
|
PaymentSuccessStatus(fee_msat=0)
|
||||||
|
if inv in completed
|
||||||
|
else PaymentPendingStatus()
|
||||||
|
)
|
||||||
|
return out
|
||||||
|
|
||||||
# ------------------------------------------------------------------ #
|
# ------------------------------------------------------------------ #
|
||||||
# misc Strike helpers #
|
# misc Strike helpers #
|
||||||
# ------------------------------------------------------------------ #
|
# ------------------------------------------------------------------ #
|
||||||
|
|
||||||
async def get_invoices(
|
|
||||||
self,
|
|
||||||
filters: str | None = None,
|
|
||||||
orderby: str | None = None,
|
|
||||||
skip: int | None = None,
|
|
||||||
top: int | None = None,
|
|
||||||
) -> dict[str, Any]:
|
|
||||||
try:
|
|
||||||
params: dict[str, Any] = {}
|
|
||||||
if filters:
|
|
||||||
params["$filter"] = filters
|
|
||||||
if orderby:
|
|
||||||
params["$orderby"] = orderby
|
|
||||||
if skip is not None:
|
|
||||||
params["$skip"] = skip
|
|
||||||
if top is not None:
|
|
||||||
params["$top"] = top
|
|
||||||
r = await self._get(
|
|
||||||
"/invoices", params=params
|
|
||||||
) # Get invoices from Strike API.
|
|
||||||
r.raise_for_status()
|
|
||||||
return r.json()
|
|
||||||
except Exception:
|
|
||||||
logger.warning("Error in get_invoices()")
|
|
||||||
return {"error": "unable to fetch invoices"}
|
|
||||||
|
|
||||||
async def _get_payment_status_by_quote_id(
|
async def _get_payment_status_by_quote_id(
|
||||||
self, checking_id: str, quote_id: str
|
self, checking_id: str, quote_id: str
|
||||||
) -> PaymentStatus | None:
|
) -> PaymentStatus | None:
|
||||||
|
|
@ -495,10 +591,19 @@ class StrikeWallet(Wallet):
|
||||||
|
|
||||||
data = resp.json()
|
data = resp.json()
|
||||||
state = data.get("state", "").upper()
|
state = data.get("state", "").upper()
|
||||||
preimage = data.get("preimage") or data.get("preImage")
|
|
||||||
|
# Extract preimage from lightning object (new API structure)
|
||||||
|
lightning_data = data.get("lightning", {})
|
||||||
|
preimage = (
|
||||||
|
lightning_data.get("preimage")
|
||||||
|
or lightning_data.get("preImage")
|
||||||
|
or data.get("preimage")
|
||||||
|
or data.get("preImage")
|
||||||
|
)
|
||||||
|
|
||||||
fee_msat = 0
|
fee_msat = 0
|
||||||
fee_obj = data.get("lightningNetworkFee") or data.get("totalFee")
|
# Updated API structure (Aug 26, 2024): fee is now in lightning.networkFee
|
||||||
|
fee_obj = lightning_data.get("networkFee") or data.get("totalFee")
|
||||||
if fee_obj and fee_obj.get("amount") and fee_obj.get("currency"):
|
if fee_obj and fee_obj.get("amount") and fee_obj.get("currency"):
|
||||||
amount_str = fee_obj.get("amount")
|
amount_str = fee_obj.get("amount")
|
||||||
currency_str = fee_obj.get("currency").upper()
|
currency_str = fee_obj.get("currency").upper()
|
||||||
|
|
@ -534,8 +639,30 @@ class StrikeWallet(Wallet):
|
||||||
if r_payment.status_code == 200:
|
if r_payment.status_code == 200:
|
||||||
data = r_payment.json()
|
data = r_payment.json()
|
||||||
state = data.get("state", "").upper()
|
state = data.get("state", "").upper()
|
||||||
preimage = None
|
|
||||||
|
# Extract data from lightning object (new API structure)
|
||||||
|
lightning_data = data.get("lightning", {})
|
||||||
|
preimage = (
|
||||||
|
lightning_data.get("preimage")
|
||||||
|
or lightning_data.get("preImage")
|
||||||
|
or data.get("preimage")
|
||||||
|
or data.get("preImage")
|
||||||
|
)
|
||||||
|
|
||||||
|
# Extract fee from new API structure
|
||||||
|
fee_obj = lightning_data.get("networkFee") or data.get("totalFee")
|
||||||
fee_msat = 0
|
fee_msat = 0
|
||||||
|
if fee_obj and fee_obj.get("amount"):
|
||||||
|
try:
|
||||||
|
fee_btc = Decimal(fee_obj.get("amount", "0"))
|
||||||
|
currency = fee_obj.get("currency", "BTC").upper()
|
||||||
|
if currency == "BTC":
|
||||||
|
fee_msat = int(fee_btc * Decimal("1e11"))
|
||||||
|
elif currency == "SAT":
|
||||||
|
fee_msat = int(fee_btc * 1000)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Error parsing fee for payment {checking_id}: {e}")
|
||||||
|
fee_msat = 0
|
||||||
|
|
||||||
if state in {"SUCCEEDED", "COMPLETED"}:
|
if state in {"SUCCEEDED", "COMPLETED"}:
|
||||||
self.pending_payments.pop(checking_id, None)
|
self.pending_payments.pop(checking_id, None)
|
||||||
|
|
@ -564,7 +691,7 @@ class StrikeWallet(Wallet):
|
||||||
)
|
)
|
||||||
if not is_invalid:
|
if not is_invalid:
|
||||||
continue
|
continue
|
||||||
logger.error(
|
logger.warning(
|
||||||
f"Payment '{checking_id}' not a valid Strike payment. "
|
f"Payment '{checking_id}' not a valid Strike payment. "
|
||||||
f"Marked as failed. Response: {r_payment.text}"
|
f"Marked as failed. Response: {r_payment.text}"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue