From 83bdca57f468f799fced20b55d98219197fa975c Mon Sep 17 00:00:00 2001 From: Sikkra <159844544+Sikkra@users.noreply.github.com> Date: Tue, 19 May 2026 11:23:39 -0500 Subject: [PATCH] Add live HF leverage preview --- frontend/index.html | 5 +++++ frontend/src/main.ts | 20 +++++++++++++++++++ frontend/src/style.css | 45 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/frontend/index.html b/frontend/index.html index f904f23..4505a37 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -404,6 +404,11 @@

Open Position

Degen +
+ Projected HF + + Move leverage to preview risk +
diff --git a/frontend/src/main.ts b/frontend/src/main.ts index fcc1ceb..3069fc5 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -1167,6 +1167,25 @@ function switchAdjustSubTab(sub: "leverage" | "add-funds") { // ── Leverage preview ────────────────────────────────────────────────────────── +function renderLiveHfPreview(hf: number) { + const preview = $("hf-live-preview"); + const value = $("hf-live-value"); + const status = $("hf-live-status"); + const min = minHF(); + const finite = Number.isFinite(hf); + const display = finite ? fmt(hf, expertMode ? 5 : 3) : hf > 0 ? "\u221E" : "--"; + const state = !finite ? (hf > 0 ? "ok" : "bad") : hf >= 1.1 ? "ok" : hf >= min ? "warn" : "bad"; + + value.textContent = display; + value.className = `hf-live-value ${state === "ok" ? "hf-ok" : state === "warn" ? "hf-warn" : "hf-bad"}`; + status.textContent = state === "ok" + ? `Safe above ${fmt(min, expertMode ? 5 : 3)} min` + : state === "warn" + ? `Near ${fmt(min, expertMode ? 5 : 3)} minimum` + : `Below ${fmt(min, expertMode ? 5 : 3)} minimum`; + preview.className = `hf-live-preview hf-live-${state}`; +} + function updatePreview() { const slider = $("leverage-slider") as HTMLInputElement; const numIn = $("leverage-input") as HTMLInputElement; @@ -1178,6 +1197,7 @@ function updatePreview() { const l = rs?.lFactor ?? 1; const hf = hfForLeverage(lev, c, l); const pos = positions.byAsset.get(selectedAsset.id); + renderLiveHfPreview(hf); // In adjust mode, use equity as the base; in add-funds mode, use the add-funds input; in open mode, use initial deposit const equity = (actionMode === "adjust" && pos) ? pos.equity diff --git a/frontend/src/style.css b/frontend/src/style.css index 0d4348f..41d6e20 100644 --- a/frontend/src/style.css +++ b/frontend/src/style.css @@ -621,6 +621,49 @@ main { flex: 1; max-width: 1200px; width: 100%; margin: 0 auto; padding: 20px 24 .slider-zone.active { opacity: 1; font-weight: 800; } .slider-zone:not(.active) { opacity: .4; } +.hf-live-preview { + min-height: 38px; + display: grid; + grid-template-columns: auto auto 1fr; + align-items: center; + gap: 10px; + margin: 0 0 10px; + padding: 8px 10px; + background: var(--metric-bg); + border: 1px solid var(--border); + border-radius: var(--r-xs); +} +.hf-live-label { + color: var(--text-2); + font-size: 11px; + font-weight: 700; + letter-spacing: .4px; + text-transform: uppercase; +} +.hf-live-value { + font-family: var(--mono); + font-size: 16px; + line-height: 1; +} +.hf-live-status { + min-width: 0; + color: var(--text-3); + font-size: 12px; + text-align: right; +} +.hf-live-preview.hf-live-ok { + background: var(--primary-glow); + border-color: var(--success-border); +} +.hf-live-preview.hf-live-warn { + background: var(--warning-bg); + border-color: var(--warning-border); +} +.hf-live-preview.hf-live-bad { + background: var(--danger-bg); + border-color: var(--danger-border); +} + /* APY chart */ .apy-chart { margin: 4px 0 10px; overflow: visible; } .apy-chart svg { width: 100%; height: 120px; display: block; overflow: visible; } @@ -1192,6 +1235,8 @@ main { flex: 1; max-width: 1200px; width: 100%; margin: 0 auto; padding: 20px 24 .swap-asset-select { width: 100%; } .slider-row { flex-wrap: wrap; } .leverage-num-input { width: 100%; margin-top: 4px; } + .hf-live-preview { grid-template-columns: 1fr auto; } + .hf-live-status { grid-column: 1 / -1; text-align: left; } #wallet-area { flex-wrap: wrap; gap: 6px; } .btn-connect { font-size: 12px; padding: 5px 10px; } .slippage-opt { padding: 2px 6px; font-size: 11px; }