resolve reivews

This commit is contained in:
9qeklajc
2026-07-07 14:29:39 +02:00
parent e2aa02307b
commit 46bbba7027
3 changed files with 52 additions and 22 deletions
+4 -7
View File
@@ -23,6 +23,7 @@ from .lightning import lightning_router
from .wallet import (
classify_redemption_error,
credit_balance,
is_mint_connection_error,
recieve_token,
send_to_lnurl,
send_token,
@@ -435,14 +436,10 @@ async def refund_wallet_endpoint(
"has_refund_address": bool(key.refund_address),
},
)
if (
"mint" in error_msg.lower()
or "connection" in error_msg.lower()
or "ConnectError" in str(type(e))
):
raise HTTPException(status_code=503, detail=f"Mint service unavailable: {error_msg}")
if is_mint_connection_error(e):
raise HTTPException(status_code=503, detail="Mint service unavailable")
else:
raise HTTPException(status_code=500, detail=f"Refund failed: {error_msg}")
raise HTTPException(status_code=500, detail="Refund failed")
await _refund_cache_set(bearer_value, result)
+8 -14
View File
@@ -14,6 +14,7 @@ from httpx import AsyncClient
from sqlmodel import select
from routstr.core.db import ApiKey, CashuTransaction
from routstr.wallet import MintConnectionError
@pytest.mark.integration
@@ -503,26 +504,19 @@ async def test_mint_unavailability_handling(
# The global mock in conftest.py is already in place,
# so we need to temporarily modify it
from unittest.mock import patch
raw_error = "Mint unavailable: Connection refused"
# Make the send_token method raise an exception
# Make the send_token method raise a typed mint connection exception.
with patch(
"routstr.balance.send_token",
side_effect=Exception("Mint unavailable: Connection refused"),
side_effect=MintConnectionError(raw_error),
):
# The exception should propagate as a 503 error (Service Unavailable)
# But we need to handle it properly
try:
response = await authenticated_client.post("/v1/wallet/refund")
# If we get here, check the status code
assert response.status_code == 503
assert "Mint service unavailable" in response.json()["detail"]
except Exception as e:
# If the exception propagates, that's also a failure scenario
assert "Mint unavailable" in str(e)
response = await authenticated_client.post("/v1/wallet/refund")
assert response.status_code == 503
assert response.json()["detail"] == "Mint service unavailable"
assert raw_error not in response.text
# Balance should remain unchanged (transaction should roll back)
# Note: Current implementation might not handle this perfectly
wallet_response = await authenticated_client.get("/v1/wallet/")
assert wallet_response.status_code == 200
assert wallet_response.json()["balance"] == 10_000_000
+40 -1
View File
@@ -340,7 +340,10 @@ async def test_apikey_refund_restores_balance_on_mint_failure() -> None:
with (
patch("routstr.balance.get_billing_key", AsyncMock(return_value=key)),
patch("routstr.balance.send_token", AsyncMock(side_effect=Exception("mint down"))),
patch(
"routstr.balance.send_token",
AsyncMock(side_effect=MintConnectionError("raw mint outage detail")),
),
patch("routstr.balance.store_cashu_transaction", AsyncMock()),
patch("routstr.balance._refund_cache_get", AsyncMock(return_value=None)),
patch("routstr.balance._refund_cache_set", AsyncMock()),
@@ -354,10 +357,46 @@ async def test_apikey_refund_restores_balance_on_mint_failure() -> None:
)
assert exc_info.value.status_code == 503
assert exc_info.value.detail == "Mint service unavailable"
assert "raw mint outage detail" not in exc_info.value.detail
# Verify two exec calls: debit + restore
assert session.exec.await_count == 2
@pytest.mark.asyncio
async def test_apikey_refund_generic_failure_is_sanitized_500() -> None:
"""Unexpected send-side failures restore balance without leaking exception text."""
from fastapi import HTTPException
key = _make_api_key(balance=5000, refund_currency="sat")
raw_error = "database secret token raw-mint-response"
session = MagicMock()
session.get = AsyncMock(return_value=key)
session.exec = AsyncMock(side_effect=[_update_result(1), _update_result(1)])
session.commit = AsyncMock()
with (
patch("routstr.balance.get_billing_key", AsyncMock(return_value=key)),
patch("routstr.balance.send_token", AsyncMock(side_effect=RuntimeError(raw_error))),
patch("routstr.balance.store_cashu_transaction", AsyncMock()),
patch("routstr.balance._refund_cache_get", AsyncMock(return_value=None)),
patch("routstr.balance._refund_cache_set", AsyncMock()),
patch("routstr.balance.logger"),
):
with pytest.raises(HTTPException) as exc_info:
await refund_wallet_endpoint(
authorization="Bearer sk-testhash",
x_cashu=None,
session=session,
)
assert exc_info.value.status_code == 500
assert exc_info.value.detail == "Refund failed"
assert raw_error not in exc_info.value.detail
assert session.exec.await_count == 2
# ---------------------------------------------------------------------------
# no-create guarantee: fresh Cashu/unknown sk- tokens must not create API keys
# ---------------------------------------------------------------------------