Add endpoint to get a single trade by ID

This commit is contained in:
counterweight 2025-12-23 15:52:02 +01:00
parent 04192799ab
commit 0c75583930
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C
2 changed files with 96 additions and 0 deletions

View file

@ -565,6 +565,29 @@ async def get_my_trades(
return [_to_exchange_response(ex, current_user.email) for ex in exchanges]
@trades_router.get("/{exchange_id}", response_model=ExchangeResponse)
async def get_my_trade(
exchange_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(require_permission(Permission.VIEW_OWN_EXCHANGES)),
) -> ExchangeResponse:
"""Get a specific trade by ID. User can only access their own trades."""
result = await db.execute(
select(Exchange).where(
and_(Exchange.id == exchange_id, Exchange.user_id == current_user.id)
)
)
exchange = result.scalar_one_or_none()
if not exchange:
raise HTTPException(
status_code=404,
detail="Trade not found or you don't have permission to view it.",
)
return _to_exchange_response(exchange, current_user.email)
@trades_router.post("/{exchange_id}/cancel", response_model=ExchangeResponse)
async def cancel_my_trade(
exchange_id: int,

View file

@ -646,6 +646,79 @@ class TestUserTrades:
assert len(data) == 2
class TestGetMyTrade:
"""Test getting a single trade by ID."""
@pytest.mark.asyncio
async def test_get_my_trade_success(self, client_factory, regular_user, admin_user):
"""Can get own trade by ID."""
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:
# Create a trade
create_response = await client.post(
"/api/exchange",
json={
"slot_start": f"{target_date}T09:00:00Z",
"direction": "buy",
"bitcoin_transfer_method": "onchain",
"eur_amount": 10000,
},
)
assert create_response.status_code == 200
trade_id = create_response.json()["id"]
# Get the trade
get_response = await client.get(f"/api/trades/{trade_id}")
assert get_response.status_code == 200
data = get_response.json()
assert data["id"] == trade_id
assert data["direction"] == "buy"
assert data["bitcoin_transfer_method"] == "onchain"
@pytest.mark.asyncio
async def test_cannot_get_other_user_trade(
self, client_factory, regular_user, alt_regular_user, admin_user
):
"""Cannot get another user's trade."""
target_date = await setup_availability_and_price(client_factory, admin_user)
with mock_price_fetcher(20000.0):
# First user creates a trade
async with client_factory.create(cookies=regular_user["cookies"]) as client:
create_response = await client.post(
"/api/exchange",
json={
"slot_start": f"{target_date}T09:00:00Z",
"direction": "buy",
"bitcoin_transfer_method": "onchain",
"eur_amount": 10000,
},
)
assert create_response.status_code == 200
trade_id = create_response.json()["id"]
# Second user tries to get it
async with client_factory.create(
cookies=alt_regular_user["cookies"]
) as client:
get_response = await client.get(f"/api/trades/{trade_id}")
assert get_response.status_code == 404
@pytest.mark.asyncio
async def test_get_nonexistent_trade_returns_404(
self, client_factory, regular_user
):
"""Getting a nonexistent trade returns 404."""
async with client_factory.create(cookies=regular_user["cookies"]) as client:
response = await client.get("/api/trades/99999")
assert response.status_code == 404
class TestCancelTrade:
"""Test cancelling trades."""