67cc084347
- Extract shared gate_transfer_lib and global transfer form on all pages - Block auto-transfer when trend pullback plans have open positions - Redirect manual transfer back to the current page after submit Co-authored-by: Cursor <cursoragent@cursor.com>
56 lines
2.0 KiB
Python
56 lines
2.0 KiB
Python
"""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
|