Files
arbitrade/tests/unit/test_kraken_rest.py
T

113 lines
3.2 KiB
Python

import httpx
import pytest
import respx
from arbitrade.config.settings import Settings
from arbitrade.exchange.kraken_rest import KrakenRestClient
@pytest.mark.asyncio
async def test_server_time_success() -> None:
settings = Settings(_env_file=None)
client = KrakenRestClient(settings)
with respx.mock(base_url=settings.kraken_rest_url) as mock_router:
mock_router.get("/0/public/Time").respond(
200,
json={"error": [], "result": {"unixtime": 1}},
)
payload = await client.server_time()
await client.close()
assert payload["unixtime"] == 1
@pytest.mark.asyncio
async def test_retry_then_success() -> None:
settings = Settings(
_env_file=None,
kraken_retry_attempts=2,
kraken_retry_base_delay_seconds=0.0,
)
client = KrakenRestClient(settings)
with respx.mock(base_url=settings.kraken_rest_url) as mock_router:
route = mock_router.get("/0/public/Time")
route.side_effect = [
httpx.ConnectError("boom"),
httpx.Response(200, json={"error": [], "result": {"unixtime": 2}}),
]
payload = await client.server_time()
await client.close()
assert payload["unixtime"] == 2
@pytest.mark.asyncio
async def test_balances_private_call_uses_headers() -> None:
settings = Settings(
_env_file=None,
KRAKEN_API_KEY="key",
KRAKEN_API_SECRET="c2VjcmV0", # base64("secret")
kraken_private_rate_limit_seconds=0.0,
)
client = KrakenRestClient(settings)
with respx.mock(base_url=settings.kraken_rest_url) as mock_router:
route = mock_router.post("/0/private/Balance").respond(
200,
json={"error": [], "result": {"ZUSD": "10.0"}},
)
payload = await client.balances()
await client.close()
request = route.calls.last.request
assert request.headers.get("API-Key") == "key"
assert request.headers.get("API-Sign")
assert payload["ZUSD"] == "10.0"
@pytest.mark.asyncio
async def test_balances_requires_credentials() -> None:
settings = Settings(
_env_file=None,
KRAKEN_API_KEY=None,
KRAKEN_API_SECRET=None,
kraken_private_rate_limit_seconds=0.0,
)
client = KrakenRestClient(settings)
with pytest.raises(RuntimeError, match="Missing Kraken API credentials"):
await client.balances()
await client.close()
def test_compliance_default_ok() -> None:
settings = Settings(_env_file=None)
client = KrakenRestClient(settings)
issues = client.validate_compliance()
assert issues == []
def test_compliance_detects_insecure_config() -> None:
settings = Settings(
_env_file=None,
KRAKEN_REST_URL="http://api.kraken.com",
KRAKEN_PRIVATE_RATE_LIMIT_SECONDS=0.0,
KRAKEN_RETRY_ATTEMPTS=0,
KRAKEN_RETRY_BASE_DELAY_SECONDS=-1.0,
)
client = KrakenRestClient(settings)
issues = client.validate_compliance()
assert any("https://" in issue for issue in issues)
assert any("below 1.0" in issue for issue in issues)
assert any("ATTEMPTS" in issue for issue in issues)
assert any("BASE_DELAY" in issue for issue in issues)