import pytest from fastapi import HTTPException from app.api import user def _make_sub(): class Sub: wallet_address = "0xabc" hl_api_key = None return Sub() class _Scalar: def __init__(self, value): self._value = value def scalar_one_or_none(self): return self._value class _Db: def __init__(self, sub): self.sub = sub self.committed = False async def execute(self, _stmt): return _Scalar(self.sub) async def commit(self): self.committed = True class _Body: wallet = "0xabc" timestamp = 123 signature = "0xsig" api_key = "0x" + "1" * 64 @pytest.mark.asyncio async def test_set_hl_api_key_saves_only_after_hyperliquid_verification(monkeypatch): sub = _make_sub() db = _Db(sub) monkeypatch.setattr(user, "verify_signed_request", lambda **_kwargs: None) monkeypatch.setattr(user, "encrypt_api_key", lambda value: f"encrypted:{value[-6:]}") calls = [] async def verify_key(**kwargs): calls.append(kwargs) monkeypatch.setattr(user, "verify_hl_api_key_can_trade", verify_key) result = await user.set_hl_api_key("0xabc", _Body(), db) assert db.committed is True assert sub.hl_api_key == "encrypted:111111" assert result.status == "ok" assert result.verified is True assert calls == [{"api_key": _Body.api_key, "account_address": "0xabc"}] @pytest.mark.asyncio async def test_set_hl_api_key_does_not_save_when_hyperliquid_verification_fails(monkeypatch): sub = _make_sub() db = _Db(sub) monkeypatch.setattr(user, "verify_signed_request", lambda **_kwargs: None) async def fail_verify(**_kwargs): raise HTTPException(422, "Hyperliquid rejected this API key") monkeypatch.setattr(user, "verify_hl_api_key_can_trade", fail_verify) with pytest.raises(HTTPException) as exc: await user.set_hl_api_key("0xabc", _Body(), db) assert exc.value.status_code == 422 assert db.committed is False assert sub.hl_api_key is None