diff options
| author | Adam Soltys <[email protected]> | 2026-10-08 13:44:24 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-08 13:44:24 -0700 |
| commit | 6206eaa76431d0bb09ffa88abb3f02b8976a9ed3 (patch) | |
| tree | 296fb5774810002fa27e795268a2f418726736a3 /tools | |
| parent | fcd023fb4b33404eb62afceba0c0232f8b25f200 (diff) | |
| download | coinosv3-6206eaa76431d0bb09ffa88abb3f02b8976a9ed3.tar.gz coinosv3-6206eaa76431d0bb09ffa88abb3f02b8976a9ed3.zip | |
Renewals show on every device: the sync snapshot carries each device's own renewals as display-only slivers (step, amounts, fee, round txid; no signing material), merged into remoteRenewals furthest-step-wins, never as actions; the coins page lists another device's renewal in progress with its round transaction until it finishes there or a 'Renewed' row syncs (two-day cap)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/ark-renewal-sync-test.js | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/tools/ark-renewal-sync-test.js b/tools/ark-renewal-sync-test.js new file mode 100644 index 0000000..af31cde --- /dev/null +++ b/tools/ark-renewal-sync-test.js @@ -0,0 +1,53 @@ +// A renewal started on one device shows on the others as in progress (a phone +// knew nothing while the laptop's round ran and the balance sat locked), is +// never adopted as an action there, and disappears once it finishes. +// Run: bun tools/ark-renewal-sync-test.js +import assert from 'node:assert/strict'; +import { slimArkForSync, mergeArkStates, remoteRenewalsInFlight } from '../src/features/ark.js'; + +const now = Date.now(); +const laptop = (step, extra = {}) => ({ + serverPubkey: 'srv', vtxos: [], movements: [], actions: [{ + id: `refresh-${now - 60_000}`, type: 'refresh', step, inputIds: ['a:0'], outKeyIndex: 9, + outAmountSat: 62212, feeSat: 125, unlockHash: 'c0'.repeat(32), fundingTxHex: 'deadbeef', outputVtxos: ['00'], ...extra, + }], +}); +let phone = { serverPubkey: 'srv', vtxos: [], movements: [], actions: [{ id: 'ln-recv-1', type: 'ln-recv', step: 'awaiting' }] }; + +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'); +phone = mergeArkStates(phone, snap); +assert.equal(phone.actions.length, 1, 'never adopted as an action of this device'); +assert.equal(remoteRenewalsInFlight(phone).length, 1); +assert.equal(remoteRenewalsInFlight(phone)[0].outAmountSat, 62212); +assert.ok(!('renewals' in phone), 'the snapshot field is not stored as is'); +console.log('✓ The other device sees the renewal in progress, as display only'); + +phone = mergeArkStates(phone, slimArkForSync(laptop('submitted', { fundingTxid: 'e9'.repeat(32) }))); +assert.equal(remoteRenewalsInFlight(phone)[0].fundingTxid, 'e9'.repeat(32)); +// an older snapshot (another slot, still at 'created') never moves it back +phone = mergeArkStates(phone, slimArkForSync(laptop('created'))); +assert.equal(phone.remoteRenewals[0].step, 'submitted'); +console.log('✓ It learns the round transaction, and a staler snapshot never moves it back'); + +phone = mergeArkStates(phone, slimArkForSync(laptop('done', { fundingTxid: 'e9'.repeat(32) }))); +assert.equal(remoteRenewalsInFlight(phone).length, 0); +console.log('✓ Finished there, it is gone here'); + +{ + let p2 = mergeArkStates({ serverPubkey: 'srv', vtxos: [], movements: [], actions: [] }, slimArkForSync(laptop('issued'))); + p2 = mergeArkStates(p2, { serverPubkey: 'srv', vtxos: [], actions: [], movements: [{ id: 'm', type: 'refresh', status: 'complete', unlockHash: 'c0'.repeat(32) }] }); + assert.equal(remoteRenewalsInFlight(p2).length, 0); + console.log('✓ A synced "Renewed" row settles it even before the final telling arrives'); +} + +{ + const own = laptop('submitted'); + const merged = mergeArkStates(own, slimArkForSync(laptop('submitted'))); + assert.equal((merged.remoteRenewals || []).length, 0, 'its own renewal never shows twice'); + const old = laptop('submitted'); old.actions[0].id = `refresh-${now - 3 * 86_400_000}`; + 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'); +} +console.log('\n✅ renewals sync across devices for display'); |
