Add Lightning amount threshold validation
This commit is contained in:
parent
28e8ba218f
commit
8936d802a6
3 changed files with 87 additions and 0 deletions
|
|
@ -33,6 +33,7 @@ from shared_constants import (
|
|||
EUR_TRADE_INCREMENT,
|
||||
EUR_TRADE_MAX,
|
||||
EUR_TRADE_MIN,
|
||||
LIGHTNING_MAX_EUR,
|
||||
PREMIUM_PERCENTAGE,
|
||||
PRICE_STALENESS_SECONDS,
|
||||
SLOT_DURATION_MINUTES,
|
||||
|
|
@ -415,6 +416,20 @@ async def create_exchange(
|
|||
detail=f"EUR amount must be a multiple of €{EUR_TRADE_INCREMENT}",
|
||||
)
|
||||
|
||||
# Validate Lightning threshold
|
||||
if (
|
||||
bitcoin_transfer_method == BitcoinTransferMethod.LIGHTNING
|
||||
and request.eur_amount > LIGHTNING_MAX_EUR * 100
|
||||
):
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=(
|
||||
f"Lightning payments are only allowed for amounts up to "
|
||||
f"€{LIGHTNING_MAX_EUR}. For amounts above €{LIGHTNING_MAX_EUR}, "
|
||||
"please use onchain transactions."
|
||||
),
|
||||
)
|
||||
|
||||
# Validate slot timing - compute valid boundaries from slot duration
|
||||
valid_minutes = tuple(range(0, 60, SLOT_DURATION_MINUTES))
|
||||
if request.slot_start.minute not in valid_minutes:
|
||||
|
|
|
|||
|
|
@ -16,3 +16,4 @@ EUR_TRADE_INCREMENT: int = _constants["exchange"]["eurTradeIncrement"]
|
|||
PREMIUM_PERCENTAGE: int = _constants["exchange"]["premiumPercentage"]
|
||||
PRICE_REFRESH_SECONDS: int = _constants["exchange"]["priceRefreshSeconds"]
|
||||
PRICE_STALENESS_SECONDS: int = _constants["exchange"]["priceStalenessSeconds"]
|
||||
LIGHTNING_MAX_EUR: int = _constants["exchange"]["lightningMaxEur"]
|
||||
|
|
|
|||
|
|
@ -324,6 +324,77 @@ class TestCreateExchange:
|
|||
assert response.status_code == 400
|
||||
assert "Invalid bitcoin_transfer_method" in response.json()["detail"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_lightning_above_threshold_rejected(
|
||||
self, client_factory, regular_user, admin_user
|
||||
):
|
||||
"""Lightning payment above threshold is rejected."""
|
||||
target_date = await setup_availability_and_price(client_factory, admin_user)
|
||||
|
||||
with mock_price_fetcher(20000.0):
|
||||
async with client_factory.create(cookies=regular_user["cookies"]) as client:
|
||||
# Try Lightning with amount above threshold (€1000 = 100000 cents)
|
||||
response = await client.post(
|
||||
"/api/exchange",
|
||||
json={
|
||||
"slot_start": f"{target_date}T09:00:00Z",
|
||||
"direction": "buy",
|
||||
"bitcoin_transfer_method": "lightning",
|
||||
"eur_amount": 110000, # €1100, above €1000 threshold
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
assert "Lightning payments are only allowed" in response.json()["detail"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_lightning_below_threshold_accepted(
|
||||
self, client_factory, regular_user, admin_user
|
||||
):
|
||||
"""Lightning payment below threshold is accepted."""
|
||||
target_date = await setup_availability_and_price(client_factory, admin_user)
|
||||
|
||||
with mock_price_fetcher(20000.0):
|
||||
async with client_factory.create(cookies=regular_user["cookies"]) as client:
|
||||
# Lightning with amount at threshold
|
||||
response = await client.post(
|
||||
"/api/exchange",
|
||||
json={
|
||||
"slot_start": f"{target_date}T09:00:00Z",
|
||||
"direction": "buy",
|
||||
"bitcoin_transfer_method": "lightning",
|
||||
"eur_amount": 100000, # €1000, exactly at threshold
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["bitcoin_transfer_method"] == "lightning"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_onchain_above_threshold_accepted(
|
||||
self, client_factory, regular_user, admin_user
|
||||
):
|
||||
"""Onchain payment above threshold is accepted."""
|
||||
target_date = await setup_availability_and_price(client_factory, admin_user)
|
||||
|
||||
with mock_price_fetcher(20000.0):
|
||||
async with client_factory.create(cookies=regular_user["cookies"]) as client:
|
||||
# Onchain with amount above Lightning threshold
|
||||
response = await client.post(
|
||||
"/api/exchange",
|
||||
json={
|
||||
"slot_start": f"{target_date}T09:00:00Z",
|
||||
"direction": "buy",
|
||||
"bitcoin_transfer_method": "onchain",
|
||||
"eur_amount": 110000, # €1100, above €1000 threshold
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["bitcoin_transfer_method"] == "onchain"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_amount_below_minimum_rejected(
|
||||
self, client_factory, regular_user, admin_user
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue