From a6c30c044a31dd1adc6a7ccf5cffff74ca2d6258 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 22 Oct 2026 23:07:20 -0700 Subject: Spending settings: the coins first, then the custody strategy as a drop-down that describes only the chosen one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adam, 2026-10-23: three descriptions at once were a wall of text. The card now sits between the coins table and Renewal, is a select of the three strategies with their prices, and shows one paragraph — the chosen strategy's. The intro is two sentences shorter. Co-Authored-By: Claude Fable 5.1 --- tools/ark/custody-ui-test.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'tools') diff --git a/tools/ark/custody-ui-test.js b/tools/ark/custody-ui-test.js index 7ebc2ea..419ed21 100644 --- a/tools/ark/custody-ui-test.js +++ b/tools/ark/custody-ui-test.js @@ -77,20 +77,20 @@ try { let tx = await text(); assert.match(tx, /Custody/); - assert.match(tx, /Allow coins to expire[\s\S]*no fees/); - assert.match(tx, /keeps its own exit until it expires/); - assert.doesNotMatch(tx, /timelock|Spending coin carries|old Coinos/, 'no jargon on the card'); - assert.match(tx, /Minimize renewal cost[\s\S]*300 sats per renewal/); - assert.match(tx, /Minimize exit cost[\s\S]*300 sats near expiry, 0\.2% \+ 300 sats when early/); - assert.match(tx, /4 hops deep/); - const checked = await page.$$eval('.ark-custody input[type=radio]', (els) => els.filter((e) => e.checked).map((e) => e.value)); - assert.deepEqual(checked, ['custodial'], 'coinos holds the coins by default'); + const opts = await page.$$eval('.ark-custody option', (es) => es.map((e) => e.value + '=' + e.textContent)); + assert.deepEqual(opts, ['custodial=Allow coins to expire · no fees', 'self=Minimize renewal cost · 300 sats per renewal', 'exit=Minimize exit cost · 300 sats near expiry, 0.2% + 300 sats when early']); + assert.equal(await page.$eval('#ark-custody-select', (e) => e.value), 'custodial', 'coins expire by default'); assert.equal(await page.evaluate(() => coopFeature.getCustody()), 'custodial'); + assert.match(await page.$eval('.ark-custody-desc', (e) => e.textContent), /keeps its own exit until it expires/); + assert.doesNotMatch(tx, /Coins renew in the last hours|Every transfer adds a hop/, 'only the chosen strategy is described'); + assert.doesNotMatch(tx, /timelock|Spending coin carries|old Coinos/, 'no jargon on the card'); + const order = await page.$$eval('.card h4, .card h3', (es) => es.map((e) => e.textContent).filter((x) => /Spending coins|Custody|Renewal/.test(x))); + assert.deepEqual(order, ['Spending coins', 'Custody', 'Renewal'], 'coins first, then the strategy, then renewal'); assert.match(tx, /held by Coinos/, 'the coin past its timelock is held, not "expired"'); assert.doesNotMatch(tx, /5,000 sats\s+expired/, 'the row never says "expired"'); assert.match(tx, /With “Allow coins to expire”, nothing renews on its own/); if (process.env.SHOT) await page.screenshot({ path: process.env.SHOT, fullPage: true }); - console.log('✓ the custody card: three tiers with their prices, coinos holding by default, a past-timelock coin shown as held'); + console.log('✓ the custody card: a drop-down of three strategies with their prices, coins expire by default, one description, a past-timelock coin shown as held'); // the unilateral exit only counts the coin still inside its timelock assert.match(tx, /Exit now/); @@ -103,13 +103,14 @@ try { console.log('✓ a unilateral exit counts only the coin still inside its timelock'); // opt into keeping the exit: persisted, the page reprices, renewal starts covering - await page.click('.ark-custody-opt[data-tier=self] input'); await sleep(400); + await page.select('#ark-custody-select', 'self'); await sleep(400); assert.equal(await page.evaluate(() => coopFeature.getCustody()), 'self'); assert.equal(await page.evaluate(() => coopApp.wallet.loadFeatureState('arkCustody')), 'self', 'saved with the wallet'); tx = await text(); assert.match(tx, /Custody choice saved/); assert.doesNotMatch(tx, /nothing renews on its own/); assert.match(tx, /renews coins automatically once they are close to expiring/); + assert.match(await page.$eval('.ark-custody-desc', (e) => e.textContent), /Coins renew in the last hours/); const calls = await page.evaluate(() => coopFeature.autoRefreshCalls); assert.deepEqual(calls[0], ['ensure', 6, 8, 1], 'backstop orders registered at once (regtest margin 6)'); assert.deepEqual(calls[1], ['refresh', ['coin-1', 'coin-2']], 'the coin past its timelock is renewed now with the small change; the deep healthy one is left alone'); @@ -117,12 +118,12 @@ try { // the exit tier also flattens the deep coin — but not the deep 800-sat one on its own merits await page.evaluate(() => { coopFeature.autoRefreshCalls.length = 0; }); - await page.click('.ark-custody-opt[data-tier=exit] input'); await sleep(400); + await page.select('#ark-custody-select', 'exit'); await sleep(400); assert.equal(await page.evaluate(() => coopFeature.getCustody()), 'exit'); const calls2 = await page.evaluate(() => coopFeature.autoRefreshCalls); assert.deepEqual(calls2[1], ['refresh', ['coin-1', 'coin-0', 'coin-2']], 'expired + deep (worth it) + small change ride one round'); console.log('✓ "Keep my exit cheap" renews the deep coin too, when the fee is under a tenth of it'); - await page.click('.ark-custody-opt[data-tier=custodial] input'); await sleep(300); + await page.select('#ark-custody-select', 'custodial'); await sleep(300); assert.equal(await page.evaluate(() => coopFeature.getCustody()), 'custodial'); assert.match(await text(), /nothing renews on its own/); console.log('✓ the other tiers switch the same way, and back'); -- cgit v1.2.3