Route sim transfer and convert through local wallets instead of OKX private API.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+133
-6
@@ -136,6 +136,36 @@ def apply_sim_hooks(app_module: Any) -> None:
|
||||
app_module.place_exchange_order = place_exchange_order
|
||||
app_module.close_exchange_order = close_exchange_order
|
||||
app_module.get_live_position_contracts = get_live_position_contracts
|
||||
|
||||
_orig_xfer = getattr(app_module, "execute_transfer_usdt", None)
|
||||
if callable(_orig_xfer):
|
||||
|
||||
def execute_transfer_usdt(amount, from_account, to_account):
|
||||
if is_sim_mode(app_module.get_db):
|
||||
from lib.sim.wallets_lib import SimWallets, normalize_sim_account
|
||||
|
||||
try:
|
||||
result = SimWallets(app_module.get_db).transfer(
|
||||
ccy="USDT",
|
||||
amount=float(amount),
|
||||
from_account=normalize_sim_account(from_account),
|
||||
to_account=normalize_sim_account(to_account),
|
||||
)
|
||||
except Exception as e:
|
||||
return False, str(e), None
|
||||
if not result.get("ok"):
|
||||
return False, result.get("detail") or result.get("msg") or "划转失败", None
|
||||
try:
|
||||
from lib.instance.instance_live_push_lib import notify_instance_balance_changed
|
||||
|
||||
notify_instance_balance_changed()
|
||||
except Exception:
|
||||
pass
|
||||
return True, "sim 划转成功", result
|
||||
return _orig_xfer(amount, from_account, to_account)
|
||||
|
||||
app_module.execute_transfer_usdt = execute_transfer_usdt
|
||||
|
||||
app_module._sim_hooks_applied = True
|
||||
|
||||
_patch_okx_options_lib(app_module)
|
||||
@@ -154,6 +184,8 @@ def _patch_okx_options_lib(app_module: Any) -> None:
|
||||
_orig_fetch_pos = opt_lib.fetch_option_positions
|
||||
_orig_ready = opt_lib.options_api_ready
|
||||
_orig_fetch_bal = opt_lib.fetch_options_balances
|
||||
_orig_transfer = opt_lib.transfer_ccy
|
||||
_orig_swap = opt_lib.spot_market_swap_usdt_usdc
|
||||
|
||||
def options_header_balances(ex, *, force: bool = False):
|
||||
try:
|
||||
@@ -169,19 +201,30 @@ def _patch_okx_options_lib(app_module: Any) -> None:
|
||||
pass
|
||||
return _orig_header(ex, force=force)
|
||||
|
||||
def fetch_options_balances(ex, *, force: bool = False):
|
||||
def fetch_options_balances(
|
||||
ex, *, force: bool = False, scope: str = "main", sub_acct: str = ""
|
||||
):
|
||||
try:
|
||||
if _GET_DB is not None and is_sim_mode(_GET_DB):
|
||||
w = broker().balances_header()
|
||||
fu = float(w["funding_usdt"])
|
||||
fc = float(w["funding_usdc"])
|
||||
tu = float(w["trading_usdt"])
|
||||
tc = float(w["trading_usdc"])
|
||||
return {
|
||||
"trading_usdc": float(w["trading_usdc"]),
|
||||
"funding_usdc": float(w["funding_usdc"]),
|
||||
"funding_usdt": float(w["funding_usdt"]),
|
||||
"trading_usdt": float(w["trading_usdt"]),
|
||||
"scope": "main",
|
||||
"funding_usdt": fu,
|
||||
"funding_usdc": fc,
|
||||
"trading_usdt": tu,
|
||||
"trading_usdc": tc,
|
||||
"funding_usdt_avail": fu,
|
||||
"funding_usdc_avail": fc,
|
||||
"trading_usdt_avail": tu,
|
||||
"trading_usdc_avail": tc,
|
||||
}
|
||||
except Exception:
|
||||
pass
|
||||
return _orig_fetch_bal(ex, force=force)
|
||||
return _orig_fetch_bal(ex, force=force, scope=scope, sub_acct=sub_acct)
|
||||
|
||||
def options_api_ready(ex):
|
||||
try:
|
||||
@@ -191,6 +234,72 @@ def _patch_okx_options_lib(app_module: Any) -> None:
|
||||
pass
|
||||
return _orig_ready(ex)
|
||||
|
||||
def transfer_ccy(ex, ccy, amount, from_acct, to_acct):
|
||||
try:
|
||||
if _GET_DB is not None and is_sim_mode(_GET_DB):
|
||||
from lib.sim.wallets_lib import SimWallets, normalize_sim_account
|
||||
|
||||
result = SimWallets(_GET_DB).transfer(
|
||||
ccy=str(ccy or "USDC"),
|
||||
amount=float(amount),
|
||||
from_account=normalize_sim_account(from_acct),
|
||||
to_account=normalize_sim_account(to_acct),
|
||||
)
|
||||
if not result.get("ok"):
|
||||
return {
|
||||
"ok": False,
|
||||
"msg": result.get("detail") or result.get("msg") or "划转失败",
|
||||
}
|
||||
try:
|
||||
from lib.instance.instance_live_push_lib import notify_instance_balance_changed
|
||||
|
||||
notify_instance_balance_changed()
|
||||
except Exception:
|
||||
pass
|
||||
return {"ok": True, "msg": "sim 划转成功", "sim": True, **result}
|
||||
except Exception as e:
|
||||
return {"ok": False, "msg": str(e)}
|
||||
return _orig_transfer(ex, ccy, amount, from_acct, to_acct)
|
||||
|
||||
def spot_market_swap_usdt_usdc(ex, *, direction: str = "usdt_to_usdc", amount: float = 0):
|
||||
try:
|
||||
if _GET_DB is not None and is_sim_mode(_GET_DB):
|
||||
from lib.sim.wallets_lib import SimWallets
|
||||
|
||||
d = (direction or "usdt_to_usdc").strip().lower()
|
||||
if d == "usdc_to_usdt":
|
||||
from_ccy, to_ccy = "USDC", "USDT"
|
||||
else:
|
||||
from_ccy, to_ccy = "USDT", "USDC"
|
||||
result = SimWallets(_GET_DB).convert(
|
||||
from_ccy=from_ccy,
|
||||
to_ccy=to_ccy,
|
||||
amount=float(amount),
|
||||
account="funding",
|
||||
)
|
||||
if not result.get("ok"):
|
||||
result = SimWallets(_GET_DB).convert(
|
||||
from_ccy=from_ccy,
|
||||
to_ccy=to_ccy,
|
||||
amount=float(amount),
|
||||
account="trading",
|
||||
)
|
||||
if not result.get("ok"):
|
||||
return {
|
||||
"ok": False,
|
||||
"msg": result.get("detail") or result.get("msg") or "兑换失败",
|
||||
}
|
||||
try:
|
||||
from lib.instance.instance_live_push_lib import notify_instance_balance_changed
|
||||
|
||||
notify_instance_balance_changed()
|
||||
except Exception:
|
||||
pass
|
||||
return {"ok": True, "msg": "sim 兑换成功(1:1)", "sim": True, **result}
|
||||
except Exception as e:
|
||||
return {"ok": False, "msg": str(e)}
|
||||
return _orig_swap(ex, direction=direction, amount=amount)
|
||||
|
||||
def fetch_option_order(ex, *, inst_id: str, ord_id: str):
|
||||
oid = str(ord_id or "")
|
||||
if oid.startswith("sim-"):
|
||||
@@ -243,6 +352,8 @@ def _patch_okx_options_lib(app_module: Any) -> None:
|
||||
opt_lib.options_header_balances = options_header_balances
|
||||
opt_lib.fetch_options_balances = fetch_options_balances
|
||||
opt_lib.options_api_ready = options_api_ready
|
||||
opt_lib.transfer_ccy = transfer_ccy
|
||||
opt_lib.spot_market_swap_usdt_usdc = spot_market_swap_usdt_usdc
|
||||
opt_lib.fetch_option_order = fetch_option_order
|
||||
opt_lib.wait_option_order_full_fill = wait_option_order_full_fill
|
||||
opt_lib.fetch_option_positions = fetch_option_positions
|
||||
@@ -279,6 +390,22 @@ def patch_options_cfg(cfg: dict[str, Any]) -> dict[str, Any]:
|
||||
if not callable(get_db):
|
||||
return cfg
|
||||
set_get_db(get_db)
|
||||
|
||||
# 与 apply_sim_hooks 对齐: cfg 里可能仍是 import 时的旧引用
|
||||
import lib.exchange.okx_options_lib as opt_lib
|
||||
|
||||
for key in (
|
||||
"transfer_ccy",
|
||||
"spot_market_swap_usdt_usdc",
|
||||
"options_api_ready",
|
||||
"fetch_options_balances",
|
||||
"fetch_option_positions",
|
||||
"fetch_option_order",
|
||||
"wait_option_order_full_fill",
|
||||
):
|
||||
if key in cfg and hasattr(opt_lib, key):
|
||||
cfg[key] = getattr(opt_lib, key)
|
||||
|
||||
live_limit = cfg.get("place_option_limit_order")
|
||||
live_market = cfg.get("place_option_market_order")
|
||||
if callable(live_limit) and callable(live_market):
|
||||
|
||||
+12
-2
@@ -21,6 +21,16 @@ _ACCT_MAP = {
|
||||
}
|
||||
|
||||
|
||||
def normalize_sim_account(account: str | None) -> str:
|
||||
"""统一账户别名: swap/unified → trading; spot → funding."""
|
||||
a = (account or "").strip().lower()
|
||||
if a in ("trading", "swap", "unified", "18"):
|
||||
return "trading"
|
||||
if a in ("funding", "spot", "6"):
|
||||
return "funding"
|
||||
return a
|
||||
|
||||
|
||||
class InsufficientFunds(RuntimeError):
|
||||
pass
|
||||
|
||||
@@ -172,8 +182,8 @@ class SimWallets:
|
||||
if amt <= 0:
|
||||
return {"ok": False, "detail": "划转金额须大于 0"}
|
||||
ccy_l = (ccy or "USDT").strip().lower()
|
||||
fa = (from_account or "").strip().lower()
|
||||
ta = (to_account or "").strip().lower()
|
||||
fa = normalize_sim_account(from_account)
|
||||
ta = normalize_sim_account(to_account)
|
||||
if fa not in ("funding", "trading") or ta not in ("funding", "trading"):
|
||||
return {"ok": False, "detail": "账户仅支持 funding / trading"}
|
||||
if fa == ta:
|
||||
|
||||
Reference in New Issue
Block a user