diff options
| author | Adam Soltys <[email protected]> | 2026-09-15 21:18:17 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-15 21:18:17 -0700 |
| commit | 229dea361b719128cf2657b6ab51aad9aca463b1 (patch) | |
| tree | 58058a54d50ff206f710c45764ad7def61f9fdd5 | |
| parent | 0ebef05d3850d312ec8098584525b22ec1b9a0de (diff) | |
| download | coinosv3-229dea361b719128cf2657b6ab51aad9aca463b1.tar.gz coinosv3-229dea361b719128cf2657b6ab51aad9aca463b1.zip | |
A tiny coin's renewal chip says "under 1 sat", not "1 sat".
The server prices a renewal on all the coins together: ppm accumulates
sub-satoshi across every input and rounds up once. The per-coin chip
rounded each coin's share up on its own, so nine 1-sat coins each showed
"renewal cost 1 sat" under a total of 4 sats — as if the page were
skipping them. The chip now shows the coin's real share: "under 1 sat"
for a sub-satoshi one, rounded otherwise, and its tooltip says how the
fee is priced.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
| -rw-r--r-- | src/features/ark.js | 12 | ||||
| -rw-r--r-- | src/i18n.js | 3 |
2 files changed, 12 insertions, 3 deletions
diff --git a/src/features/ark.js b/src/features/ark.js index e0c8f19..fe1fe90 100644 --- a/src/features/ark.js +++ b/src/features/ark.js @@ -2044,7 +2044,15 @@ export function arkFeature(ctx) { // bracket it's free, where the wallet renews on its own anyway. const table = ((mgr.info || {}).refreshFees || {}).ppmExpiryTable || []; const ppmFor = (blocks) => (table.filter((e) => e.thresholdBlocks <= blocks).pop()?.ppm) ?? 0; - const feeNowOf = (v) => Math.ceil((v.amountSat * ppmFor((v.expiryHeight || 0) - tip)) / 1_000_000); + // A coin's SHARE of the renewal fee, fractional: the server totals the + // ppm across every coin in the round and rounds up once (refreshFee), so + // a 1-sat coin costs a few thousandths of a sat, not the 1 sat a + // per-coin ceiling used to print — nine such chips summing past the + // real total made it look as if the page were skipping them. + const feeNowOf = (v) => (v.amountSat * ppmFor((v.expiryHeight || 0) - tip)) / 1_000_000; + const renewChip = (share) => share <= 0 ? t('arkDepthFree') + : share < 1 ? t('arkCoinsChipRenewTiny') + : fmtAmount(Math.round(share)) + ' ' + unitLabel(); const span = (blocks) => { if (blocks >= 144) { const d = Math.round(blocks / 144); @@ -2125,7 +2133,7 @@ export function arkFeature(ctx) { h('span', { class: 'coin-chip', title: t('arkCoinsChipExitTitle') }, t('arkCoinsChipExit', { fee: xf == null ? '—' : fmtAmount(xf) + ' ' + unitLabel() })), h('span', { class: 'coin-chip', title: t('arkCoinsChipRenewTitle') }, - t('arkCoinsChipRenew', { fee: f > 0 ? fmtAmount(f) + ' ' + unitLabel() : t('arkDepthFree') }))))); + t('arkCoinsChipRenew', { fee: renewChip(f) }))))); })), h('p', { class: 'small faint', style: 'margin:4px 0 0' }, t('arkCoinsExpiryNote'))), h('div', { class: 'card col', style: 'gap:8px' }, diff --git a/src/i18n.js b/src/i18n.js index d7781cd..bfd6ff8 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -310,7 +310,8 @@ const STR = { arkCoinsChipExp: 'expiry {d}', arkCoinsChipExit: 'exit cost {fee}', arkCoinsChipRenew: 'renewal cost {fee}', - arkCoinsChipRenewTitle: 'What renewing this coin costs', + arkCoinsChipRenewTitle: 'This coin’s share of the renewal fee — the fee is priced on all the coins together and rounded up once, so tiny shares add almost nothing', + arkCoinsChipRenewTiny: 'under 1 sat', arkCoinsChipExpTitle: 'Time until this coin needs renewal', arkCoinsChipExitTitle: 'What pulling this coin on-chain by itself would cost', arkFeeChain: 'On-chain fee', |
