aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-27 11:19:07 -0700
committerAdam Soltys <[email protected]>2026-08-27 11:19:07 -0700
commit340cb3704620ec4bf7ebafcd1ac1a1343251c14b (patch)
treea4c2ad3bf93acee512e719deba53a976465008db
parentb11e3b50483ae254caccebe220275863eb762a47 (diff)
downloadcoinosv3-340cb3704620ec4bf7ebafcd1ac1a1343251c14b.tar.gz
coinosv3-340cb3704620ec4bf7ebafcd1ac1a1343251c14b.zip
Renewal stops billing for tidiness: six refund coins after a failed payment no longer trigger a top-bracket consolidation (multi-input sends made fragmentation cheap to live with — the trigger moves to the 24-input ceiling), and the history line for a refresh now names the fee it paid
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
-rw-r--r--src/ark/manager.js2
-rw-r--r--src/features/ark.js7
2 files changed, 7 insertions, 2 deletions
diff --git a/src/ark/manager.js b/src/ark/manager.js
index eef2ec9..1129c38 100644
--- a/src/ark/manager.js
+++ b/src/ark/manager.js
@@ -1627,7 +1627,7 @@ export class ArkManager {
}
for (const v of inputRecs) v.state = 'spent';
action.step = 'done';
- this._movement({ type: 'refresh', amountSat: action.outAmountSat, status: 'complete', detail: `${inputRecs.length} in -> ${newVtxos.length} out` });
+ this._movement({ type: 'refresh', amountSat: action.outAmountSat, status: 'complete', detail: `${inputRecs.length} in -> ${newVtxos.length} out${action.feeSat ? ` · fee ${action.feeSat} sat` : ''}` });
this._save();
}
}
diff --git a/src/features/ark.js b/src/features/ark.js
index 9aa43c2..59bdb10 100644
--- a/src/features/ark.js
+++ b/src/features/ark.js
@@ -1855,7 +1855,12 @@ export function arkFeature(ctx) {
const tip = await mgr.chain.tipHeight();
const RENEW_BLOCKS = getNetwork() === 'regtest' ? 24 : 1008; // ~1 week of margin on mainnet
const expiring = spendables.some((v) => v.expiryHeight && v.expiryHeight - tip < RENEW_BLOCKS);
- const fragmented = spendables.length >= 6;
+ // Fragmentation alone is no longer worth paying for: multi-input sends
+ // handle up to 24 coins, and consolidating FRESH coins bills the round
+ // fee's top ppm bracket (a burst of refund coins after failed payments
+ // once cost a user ~1% overnight). Consolidate only when the coin count
+ // itself approaches the 24-input send ceiling.
+ const fragmented = spendables.length >= 20;
const totalSat = spendables.reduce((n, v) => n + v.amountSat, 0);
const renewable = totalSat - mgr.refreshFee(spendables, tip) >= 330;
if (expiring && !renewable) {