fix(binance): show full funding wallet USDT balance
Sum free+locked/freeze from ccxt funding balance and fall back to get-funding-asset SAPI so the header matches Binance APP funding account. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2599,23 +2599,65 @@ def exchange_private_api_configured():
|
||||
return bool(BINANCE_API_KEY and BINANCE_API_SECRET)
|
||||
|
||||
|
||||
def _float_balance_field(val):
|
||||
if val is None or val == "":
|
||||
return None
|
||||
try:
|
||||
return float(val)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def _extract_usdt_total(balance):
|
||||
usdt_info = balance.get("USDT", {}) if isinstance(balance, dict) else {}
|
||||
total_map = balance.get("total", {}) if isinstance(balance, dict) else {}
|
||||
free_map = balance.get("free", {}) if isinstance(balance, dict) else {}
|
||||
used_map = balance.get("used", {}) if isinstance(balance, dict) else {}
|
||||
total = usdt_info.get("total")
|
||||
if total is None:
|
||||
total = usdt_info.get("equity")
|
||||
if total is None:
|
||||
total = total_map.get("USDT")
|
||||
if total is None:
|
||||
total = usdt_info.get("free")
|
||||
if total is None:
|
||||
total = free_map.get("USDT")
|
||||
try:
|
||||
return float(total) if total is not None else None
|
||||
except Exception:
|
||||
if total is not None:
|
||||
fv = _float_balance_field(total)
|
||||
if fv is not None:
|
||||
return fv
|
||||
free = usdt_info.get("free")
|
||||
if free is None:
|
||||
free = free_map.get("USDT")
|
||||
used = usdt_info.get("used")
|
||||
if used is None:
|
||||
used = used_map.get("USDT")
|
||||
if used is None:
|
||||
used = usdt_info.get("locked")
|
||||
free_f = _float_balance_field(free)
|
||||
used_f = _float_balance_field(used) or 0.0
|
||||
if free_f is not None:
|
||||
return free_f + used_f
|
||||
return None
|
||||
|
||||
|
||||
def _parse_binance_funding_asset_rows(rows):
|
||||
"""解析 /sapi/v1/asset/get-funding-asset:USDT 总额 = free + freeze + locked + withdrawing。"""
|
||||
if isinstance(rows, dict):
|
||||
rows = [rows]
|
||||
if not isinstance(rows, list):
|
||||
return None
|
||||
for row in rows:
|
||||
if not isinstance(row, dict):
|
||||
continue
|
||||
if str(row.get("asset") or "").upper() != "USDT":
|
||||
continue
|
||||
parts = [
|
||||
_float_balance_field(row.get("free")),
|
||||
_float_balance_field(row.get("freeze")),
|
||||
_float_balance_field(row.get("locked")),
|
||||
_float_balance_field(row.get("withdrawing")),
|
||||
]
|
||||
nums = [p for p in parts if p is not None]
|
||||
if nums:
|
||||
return sum(nums)
|
||||
return None
|
||||
|
||||
|
||||
def _extract_usdt_free(balance):
|
||||
@@ -2690,7 +2732,7 @@ def _fetch_binance_swap_usdt_free():
|
||||
|
||||
|
||||
def _fetch_binance_funding_usdt():
|
||||
"""Binance 资金账户(Funding Wallet)USDT 总额。"""
|
||||
"""Binance 资金账户(Funding Wallet)USDT 总额(free+冻结+锁定,与 APP 资金账户一致)。"""
|
||||
try:
|
||||
ensure_markets_loaded()
|
||||
bal = exchange.fetch_balance(params={"type": "funding"})
|
||||
@@ -2699,6 +2741,22 @@ def _fetch_binance_funding_usdt():
|
||||
return float(val)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
ensure_markets_loaded()
|
||||
raw = exchange.sapiPostAssetGetFundingAsset({"asset": "USDT"})
|
||||
val = _parse_binance_funding_asset_rows(raw)
|
||||
if val is not None:
|
||||
return float(val)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
ensure_markets_loaded()
|
||||
raw = exchange.sapiPostAssetGetFundingAsset({})
|
||||
val = _parse_binance_funding_asset_rows(raw)
|
||||
if val is not None:
|
||||
return float(val)
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user