aboutsummaryrefslogtreecommitdiffstats
path: root/tools/ark/custody-test.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-10-22 22:06:01 -0700
committerAdam Soltys <[email protected]>2026-10-22 22:06:01 -0700
commitf4997d29a0c97eac61338448854c7ab9724cdc92 (patch)
tree14f2d56a06bd4bfb093c6bb5f6a21a0321de1dfa /tools/ark/custody-test.js
parent648a5503089d33232855925a24ff60f78cab6df4 (diff)
downloadcoinosv3-f4997d29a0c97eac61338448854c7ab9724cdc92.tar.gz
coinosv3-f4997d29a0c97eac61338448854c7ab9724cdc92.zip
The third custody tier keeps exits cheap by depth, not by date: "Keep my exit cheap" renews a coin once its history is four hops deep
Why: a unilateral exit publishes one on-chain transaction per off-chain hop, so depth — not age — is what makes an exit expensive, and a renewal a week before expiry flattens exactly the same history a renewal in the last hours does. The week-ahead "early" tier only guarded against the server being unreachable at the very end, which is not the case worth selling. (Adam, 2026-10-23.) exit = self (last-hours renewal, free bracket + base, the same grid-snapped backstop) plus: any coin whose genesis chain is 4+ hops deep is renewed in the next round the app runs, paying the top bracket + base — but only when that fee is under a tenth of the coin (flattening a 21-sat coin for 300 sats helps nobody; its exit is uneconomic anyway). Deep coins ride along with an expiry renewal when one is due, or get a round of their own. The server-side backstop stays near-expiry only: depth changes only while the wallet transacts, i.e. while the app is open. A stored 'early' reads as 'exit'. Card copy says what the hop count means and what the two prices are for. Co-Authored-By: Claude Fable 5.1 <[email protected]>
Diffstat (limited to 'tools/ark/custody-test.js')
-rw-r--r--tools/ark/custody-test.js14
1 files changed, 6 insertions, 8 deletions
diff --git a/tools/ark/custody-test.js b/tools/ark/custody-test.js
index da1079c..f8106b7 100644
--- a/tools/ark/custody-test.js
+++ b/tools/ark/custody-test.js
@@ -9,18 +9,16 @@ import { ArkManager, renewPolicy, CUSTODY_TIERS, MAX_SEND_INPUTS } from '../../s
import { validateVtxo, VtxoValidationError } from '../../src/ark/validate.js';
// policies
-assert.deepEqual(CUSTODY_TIERS, ['custodial', 'self', 'early']);
+assert.deepEqual(CUSTODY_TIERS, ['custodial', 'self', 'exit']);
assert.equal(renewPolicy('custodial', 'mainnet'), null, 'the default tier renews nothing');
assert.equal(renewPolicy('nonsense', 'mainnet'), null);
assert.deepEqual(renewPolicy('self', 'mainnet'), { window: 96, margin: 36, grid: 48 });
-assert.deepEqual(renewPolicy('early', 'mainnet'), { window: 1008, margin: 1008, grid: 144 });
+assert.deepEqual(renewPolicy('exit', 'mainnet'), { window: 96, margin: 36, grid: 48, maxDepth: 4 }, 'exit = self + a depth trigger');
+assert.deepEqual(renewPolicy('early', 'mainnet'), renewPolicy('exit', 'mainnet'), 'the old name still means the exit tier');
assert.deepEqual(renewPolicy('self', 'regtest'), { window: 24, margin: 6, grid: 1 });
-// the snap never leaves the bracket: self stays under 96 blocks out, early under 2160
-for (let h = 100000; h < 100200; h++) {
- const s = h - 36; assert.ok(h - (s - (s % 48)) < 96);
- const e = h - 1008; assert.ok(h - (e - (e % 144)) < 2160 && h - (e - (e % 144)) >= 199);
-}
-console.log('✓ renewal policies: custodial renews nothing; self and early aim inside one fee bracket');
+// the snap never leaves the free bracket: under 96 blocks out
+for (let h = 100000; h < 100200; h++) { const s = h - 36; assert.ok(h - (s - (s % 48)) < 96); }
+console.log('✓ renewal policies: custodial renews nothing; self and exit aim inside the free bracket');
const mk = (honorsExpired) => {
const mgr = new ArkManager({ account: null, storage: { load: () => null, save() {} }, arkUrl: 'http://x', esploraUrl: 'http://y', network: 'mainnet', honorsExpired });