"""Credential preflight: discover what the configured keys can do without ever placing a live order.""" from __future__ import annotations import time from decimal import Decimal from typing import Any from ktrade.api.deps import AppState from ktrade.kraken.rest import KrakenAPIError, KrakenREST async def _probe(rest: KrakenREST, name: str, coro) -> dict[str, Any]: # noqa: ANN001 try: await coro return {"ok": True} except KrakenAPIError as e: return {"ok": False, "permission_denied": e.is_permission, "error": str(e)} except Exception as e: # noqa: BLE001 return {"ok": False, "error": str(e)} async def run_preflight(st: AppState) -> dict[str, Any]: out: dict[str, Any] = {"checked_at": time.time(), "data_key": None, "trade_key": None} s = st.settings if s.has_data_key(): rest = st.rest d: dict[str, Any] = {} d["balance"] = await _probe(rest, "balance", rest.balance()) d["open_orders"] = await _probe(rest, "open_orders", rest.open_orders()) d["trade_volume"] = await _probe(rest, "trade_volume", rest.trade_volume(["XXBTZUSD"])) d["ws_token"] = await _probe(rest, "ws_token", rest.websockets_token()) # Trade-permission probe: validate-only order that could never execute (price = 10% of market, min size, # expires in 5 s). The data key SHOULD fail this with Permission denied (least privilege). d["trade_permission"] = await _trade_probe(rest) if d["trade_permission"].get("has_trade_permission"): d["warning"] = "The data/account key has order permission — least-privilege violated; create a read-only key for data." out["data_key"] = d if s.has_trade_key(): trade_rest = KrakenREST(s.kraken_rest_url, s.kraken_trade_api_key, s.kraken_trade_api_secret, s.kraken_tier) try: out["trade_key"] = {"trade_permission": await _trade_probe(trade_rest), "note": "live mode is disabled (feature flag + UI activation required)"} finally: await trade_rest.aclose() return out async def _trade_probe(rest: KrakenREST) -> dict[str, Any]: try: tick = await rest.ticker(["XXBTZUSD"]) last = Decimal(next(iter(tick.values()))["c"][0]) price = (last * Decimal("0.10")).quantize(Decimal("0.1")) r = await rest.add_order(pair="XXBTZUSD", side="buy", ordertype="limit", volume="0.0001", price=str(price), timeinforce="GTC", validate=True) return {"has_trade_permission": True, "validated": r.get("descr")} except KrakenAPIError as e: if e.is_permission: return {"has_trade_permission": False, "error": str(e)} # any other validation error means the permission check passed return {"has_trade_permission": True, "error": str(e)} except Exception as e: # noqa: BLE001 return {"has_trade_permission": None, "error": str(e)}