"""Gate.io 资金划转(crypto_monitor_gate / crypto_monitor_gate_bot 共用)。""" from __future__ import annotations from typing import Any, Callable, Optional INVALID_KEY_HINT = ( "。常见原因:① GATE_API_SECRET 错误或 .env 里多了空格/换行;② IP 白名单未包含当前服务器出口 IP;" "③ Gate「交易账户」类 API Key 若不支持钱包接口则无法走账户内划转 POST /wallet/transfers(需在官网确认该 Key 类型是否开放划转);" "④ Key 已重置或权限变更。你已勾选现货/统一账户仍报错时,优先核对 Secret 与白名单。" ) def execute_transfer_usdt( exchange, amount: float, from_account: str, to_account: str, *, transfer_ccy: str = "USDT", ensure_live_ready: Callable[[], tuple[bool, str]], ensure_markets_loaded: Optional[Callable[[], None]] = None, ) -> tuple[bool, str, Any]: if amount <= 0: return False, "划转金额必须大于0", None ok_live, reason = ensure_live_ready() if not ok_live: return False, reason, None if ensure_markets_loaded: try: ensure_markets_loaded() except Exception: pass try: resp = exchange.transfer(transfer_ccy, float(amount), from_account, to_account) return True, "划转成功", resp except Exception as e: msg = str(e) if "INVALID_KEY" in msg or "Invalid key" in msg: msg += INVALID_KEY_HINT return False, msg, None def count_auto_transfer_blockers(conn, *, count_order_monitors: Callable[[Any], int]) -> int: """自动划转持仓守卫:order_monitors active + 趋势回调已开仓计划。""" n = int(count_order_monitors(conn) or 0) if n > 0: return n try: row = conn.execute( "SELECT COUNT(*) FROM trend_pullback_plans " "WHERE status='active' AND COALESCE(first_order_done, 0) != 0" ).fetchone() return int(row[0] or 0) if row else 0 except Exception: return n