Prevent env autofill from overwriting OKX API keys when saving hedge settings.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2735,9 +2735,12 @@ def resolve_order_entry_price(order_resp, exchange_symbol, fallback_price):
|
||||
|
||||
|
||||
def get_contract_size(exchange_symbol):
|
||||
ensure_markets_loaded()
|
||||
market = exchange.market(exchange_symbol)
|
||||
return float(market.get("contractSize") or 1)
|
||||
try:
|
||||
ensure_markets_loaded()
|
||||
market = exchange.market(exchange_symbol)
|
||||
return float(market.get("contractSize") or 1)
|
||||
except Exception:
|
||||
return 1.0
|
||||
|
||||
|
||||
def parse_positive_float(value):
|
||||
@@ -6945,11 +6948,14 @@ def api_account_snapshot():
|
||||
except Exception:
|
||||
return exchange.fetch_positions() or []
|
||||
|
||||
unrealized_pnl = resolve_instance_unrealized_pnl(
|
||||
_okx_positions,
|
||||
active_pnl_rows,
|
||||
get_live_position_exchange_metrics,
|
||||
)
|
||||
try:
|
||||
unrealized_pnl = resolve_instance_unrealized_pnl(
|
||||
_okx_positions,
|
||||
active_pnl_rows,
|
||||
get_live_position_exchange_metrics,
|
||||
)
|
||||
except Exception:
|
||||
unrealized_pnl = None
|
||||
options_unrealized_pnl = None
|
||||
if OKX_OPTIONS_ENABLED and exchange_options.apiKey:
|
||||
try:
|
||||
|
||||
@@ -202,8 +202,21 @@
|
||||
input = document.createElement("input");
|
||||
input.id = "env-f-" + field.key;
|
||||
input.type = "password";
|
||||
input.autocomplete = "off";
|
||||
// 防止浏览器把登录密码自动填进 API Key/Secret(保存对冲开关时曾误写入密钥)
|
||||
input.autocomplete = "new-password";
|
||||
input.setAttribute("data-lpignore", "true");
|
||||
input.setAttribute("data-1p-ignore", "true");
|
||||
input.setAttribute("data-form-type", "other");
|
||||
input.readOnly = true;
|
||||
input.addEventListener("focus", function () {
|
||||
input.readOnly = false;
|
||||
});
|
||||
if (field.sensitive) {
|
||||
input.dataset.envSensitive = "1";
|
||||
input.dataset.envDirty = "0";
|
||||
input.addEventListener("input", function () {
|
||||
input.dataset.envDirty = "1";
|
||||
});
|
||||
if (field.has_value) {
|
||||
const cur = document.createElement("div");
|
||||
cur.className = "env-sensitive-current muted";
|
||||
@@ -219,6 +232,7 @@
|
||||
input.placeholder = field.has_value ? "修改时填写新值,留空不修改" : "请输入";
|
||||
} else {
|
||||
input.type = "text";
|
||||
input.autocomplete = "off";
|
||||
input.value = field.current || field.default || "";
|
||||
}
|
||||
}
|
||||
@@ -309,6 +323,10 @@
|
||||
const values = {};
|
||||
const scope = root || document;
|
||||
scope.querySelectorAll(".env-field-input[data-env-key]").forEach((el) => {
|
||||
if (el.dataset.envSensitive === "1" && el.dataset.envDirty !== "1") {
|
||||
// 未改动过的敏感项不提交,避免浏览器自动填充覆盖已有密钥
|
||||
return;
|
||||
}
|
||||
values[el.dataset.envKey] = el.value;
|
||||
});
|
||||
return values;
|
||||
|
||||
Vendored
+4
@@ -275,6 +275,10 @@ def validate_env_updates(groups: list[dict], updates: dict[str, str]) -> tuple[d
|
||||
val = str(value).strip()
|
||||
if allowed[key].get("sensitive") and (val == "" or (val.startswith("****") and len(val) <= 8)):
|
||||
continue
|
||||
# API Key 被密码管理器/自动填充成登录密码时通常很短;OKX Key 一般为 36 位
|
||||
if key.endswith("_API_KEY") and 0 < len(val) < 16:
|
||||
errors.append(f"{key} 长度异常,疑似自动填充;留空则不修改已有密钥")
|
||||
continue
|
||||
ftype = allowed[key].get("type")
|
||||
if ftype == "bool":
|
||||
low = val.lower()
|
||||
|
||||
@@ -105,18 +105,21 @@ def total_funds_usdt(
|
||||
options_funding_usdt: float | None = None,
|
||||
options_trading_usdt: float | None = None,
|
||||
) -> float | None:
|
||||
if funding_usdt is None:
|
||||
parts = [
|
||||
funding_usdt,
|
||||
trading_usdt,
|
||||
options_funding_usdc,
|
||||
options_funding_usdt,
|
||||
options_trading_usdc,
|
||||
options_trading_usdt,
|
||||
]
|
||||
if all(v is None for v in parts):
|
||||
return None
|
||||
try:
|
||||
total = float(funding_usdt) + float(trading_usdt or 0)
|
||||
if options_funding_usdc is not None:
|
||||
total += float(options_funding_usdc)
|
||||
if options_funding_usdt is not None:
|
||||
total += float(options_funding_usdt)
|
||||
if options_trading_usdc is not None:
|
||||
total += float(options_trading_usdc)
|
||||
if options_trading_usdt is not None:
|
||||
total += float(options_trading_usdt)
|
||||
total = 0.0
|
||||
for v in parts:
|
||||
if v is not None:
|
||||
total += float(v)
|
||||
return round(total, 2)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
@@ -108,7 +108,7 @@ const ORDER_ENTRY_MODEL_CODE_TO_CATEGORY = {{ entry_model_code_to_category | toj
|
||||
<script>
|
||||
window.__INSTANCE_DISPLAY__ = {{ display | tojson }};
|
||||
</script>
|
||||
<script src="/static/instance_settings_prefs.js?v=12"></script>
|
||||
<script src="/static/instance_settings_prefs.js?v=13"></script>
|
||||
<script src="/static/instance_live.js?v=5"></script>
|
||||
<script src="/static/instance_embed.js?v=23"></script>
|
||||
</body>
|
||||
|
||||
@@ -2160,6 +2160,6 @@ setInterval(refreshPriceSnapshotConditional, {{ price_refresh_seconds * 1000 }})
|
||||
<script>
|
||||
window.__INSTANCE_DISPLAY__ = {{ display | tojson }};
|
||||
</script>
|
||||
<script src="/static/instance_settings_prefs.js?v=12"></script>
|
||||
<script src="/static/instance_settings_prefs.js?v=13"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user