diff options
| author | Adam Soltys <[email protected]> | 2026-08-29 07:48:29 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-08-29 07:48:29 -0700 |
| commit | 8a3a76fae6b0a3b8930306b66ebde586438e379d (patch) | |
| tree | 4b3933e262a5f70d2945b0df627c118c4100be0a /src/features | |
| parent | 5f636a75b1230202993d6f794c18bf2017971478 (diff) | |
| download | coinosv3-8a3a76fae6b0a3b8930306b66ebde586438e379d.tar.gz coinosv3-8a3a76fae6b0a3b8930306b66ebde586438e379d.zip | |
The coins table tightens up: an Exit fee column prices pulling each coin on-chain by itself, expiry reads as a countdown (14d, 13h) instead of a date, and depth is just the number
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
Diffstat (limited to 'src/features')
| -rw-r--r-- | src/features/ark.js | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/src/features/ark.js b/src/features/ark.js index 1e6782b..e0bd147 100644 --- a/src/features/ark.js +++ b/src/features/ark.js @@ -1577,8 +1577,23 @@ export function arkFeature(ctx) { const feeRate = Math.max(1, (wallet.feeRates && wallet.feeRates.halfHourFee) || 2); const afterFee = Math.ceil(530 * feeRate); const depthOf = (v) => { try { return mgr._decoded(v).genesis.length; } catch { return null; } }; - const expiresOf = (v) => (v.expiryHeight && tip - ? new Date(Date.now() + (v.expiryHeight - tip) * 600_000).toLocaleDateString() : '—'); + // relative and terse — "14d" / "13h" — a date says less than a countdown + const expiresOf = (v) => { + if (!v.expiryHeight || !tip) return '—'; + const blocks = v.expiryHeight - tip; + if (blocks <= 0) return '0h'; + return blocks >= 144 ? Math.round(blocks / 144) + 'd' : Math.max(1, Math.round(blocks / 6)) + 'h'; + }; + // what pulling THIS coin on-chain alone would cost: every hop's fee + // child plus the claim, at today's rate (the whole-balance figure below + // is the same sum over all coins) + const exitFeeOf = (v) => { + try { + let f = Math.ceil(150 * feeRate); + for (const txi of signedExitTxs(mgr._decoded(v), mgr.serverPub)) f += Math.ceil((txi.vsize + 130) * feeRate); + return f; + } catch { return null; } + }; // The server prices a renewal by how much lifetime each coin still // carries (its ppm bracket) — waiting IS cheaper, and inside the final // bracket it's free, where the wallet renews on its own anyway. @@ -1636,10 +1651,12 @@ export function arkFeature(ctx) { render(); }, t('arkCoinsSelectAll')), head(t('arkCoinsColAmount')), head(t('arkCoinsColExpires'), 'text-align:center'), - head(t('arkCoinsColDepth'), 'text-align:center'), head(t('arkCoinsColFee'), 'text-align:right')), + head(t('arkCoinsColDepth'), 'text-align:center'), head(t('arkCoinsColExitFee'), 'text-align:center'), + head(t('arkCoinsColFee'), 'text-align:right')), ...spend.map((v) => { const d = depthOf(v); const f = feeNowOf(v); + const xf = exitFeeOf(v); return h('div', { class: 'row gap6', style: 'align-items:center' }, tick(sel.has(v.id), (e) => { e.target.checked ? sel.add(v.id) : sel.delete(v.id); @@ -1647,7 +1664,8 @@ export function arkFeature(ctx) { }), cell(fmtAmount(v.amountSat) + ' ' + unitLabel()), cell(expiresOf(v), 'text-align:center'), - cell(d == null ? '—' : d === 1 ? t('arkCoinsHop') : t('arkCoinsHops', { n: d }), 'text-align:center'), + cell(d == null ? '—' : String(d), 'text-align:center'), + cell(xf == null ? '—' : fmtAmount(xf), 'text-align:center'), cell(f > 0 ? fmtAmount(f) : t('arkDepthFree'), 'text-align:right')); })), h('p', { class: 'small faint', style: 'margin:4px 0 0' }, t('arkCoinsExpiryNote'))), |
