diff options
| author | Adam Soltys <[email protected]> | 2026-10-08 13:48:00 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-08 13:48:00 -0700 |
| commit | 175e513273bfb2a362f9a08e3da5d5460a1d91c0 (patch) | |
| tree | 1220829278076ee110fc4e81db124590674c0a34 /tools | |
| parent | 6206eaa76431d0bb09ffa88abb3f02b8976a9ed3 (diff) | |
| download | coinosv3-175e513273bfb2a362f9a08e3da5d5460a1d91c0.tar.gz coinosv3-175e513273bfb2a362f9a08e3da5d5460a1d91c0.zip | |
Coins in another device's renewal are busy here too: the renewal sliver names its inputs, and ArkManager._free / freeCoins exclude coins an in-flight remote renewal holds from balance (counted pending), send/LN/offboard/exit selection, auto-renew, the backstop and the coins page (greyed with the round). Freed the moment that renewal reads finished, failed or lapsed
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/ark-renewal-sync-test.js | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/tools/ark-renewal-sync-test.js b/tools/ark-renewal-sync-test.js index af31cde..b29f832 100644 --- a/tools/ark-renewal-sync-test.js +++ b/tools/ark-renewal-sync-test.js @@ -4,6 +4,7 @@ // Run: bun tools/ark-renewal-sync-test.js import assert from 'node:assert/strict'; import { slimArkForSync, mergeArkStates, remoteRenewalsInFlight } from '../src/features/ark.js'; +import { ArkManager } from '../src/ark/manager.js'; const now = Date.now(); const laptop = (step, extra = {}) => ({ @@ -16,7 +17,8 @@ let phone = { serverPubkey: 'srv', vtxos: [], movements: [], actions: [{ id: 'ln const snap = slimArkForSync(laptop('submitted')); assert.equal(snap.renewals.length, 1); -assert.ok(!('fundingTxHex' in snap.renewals[0]) && !('outputVtxos' in snap.renewals[0]) && !('inputIds' in snap.renewals[0]), 'display fields only'); +assert.ok(!('fundingTxHex' in snap.renewals[0]) && !('outputVtxos' in snap.renewals[0]), 'no signing material'); +assert.deepEqual(snap.renewals[0].inputIds, ['a:0'], 'names the coins it holds'); phone = mergeArkStates(phone, snap); assert.equal(phone.actions.length, 1, 'never adopted as an action of this device'); assert.equal(remoteRenewalsInFlight(phone).length, 1); @@ -50,4 +52,21 @@ console.log('✓ Finished there, it is gone here'); assert.equal(mergeArkStates(phone, slimArkForSync(old)).remoteRenewals.filter((r) => r.id === old.actions[0].id).length, 0); console.log('✓ The device that owns it never sees itself as remote; a renewal begun days ago is dropped'); } +{ + // the phone holds the laptop's renewal coin as spendable in its own records + const coin = (id, amountSat) => ({ id, amountSat, state: 'spendable', expiryHeight: 999_999, bytes: 'AA==' }); + let st = { serverPubkey: 'srv', vtxos: [coin('a:0', 62337), coin('z:0', 1000)], movements: [], actions: [] }; + st = mergeArkStates(st, slimArkForSync(laptop('submitted'))); + const mgr = new ArkManager({ storage: { save() {} }, arkUrl: 'http://test.invalid' }); + mgr.state = st; mgr._tipH = 1000; + assert.deepEqual(mgr.balance(), { spendableSat: 1000, pendingSat: 62337, boardingSat: 0, expiredSat: 0 }); + assert.deepEqual(mgr._selectInputs(500).map((v) => v.id), ['z:0']); + assert.throws(() => mgr._selectInputs(2000)); + await assert.rejects(mgr.refresh(['a:0']), /no spendable/); + console.log('✓ Its coins count as pending here and are never offered for a send or a renewal'); + st = mergeArkStates(st, slimArkForSync(laptop('failed'))); + mgr.state = st; + assert.equal(mgr.balance().spendableSat, 63337, 'a renewal that failed there frees them here'); + console.log('✓ Failed there, its coins are free again here'); +} console.log('\n✅ renewals sync across devices for display'); |
