diff options
| author | Adam Soltys <[email protected]> | 2026-10-07 12:52:14 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-07 12:52:14 -0700 |
| commit | 6faf6b6fe49b8e51a38e0106c858341faf2145ef (patch) | |
| tree | dc7fe7ebe86552f166a980cb046563c9b651de97 /tools/ark | |
| parent | 7c76b28b3e52622f8a8f734df7478ec8ba5428cf (diff) | |
| download | coinosv3-6faf6b6fe49b8e51a38e0106c858341faf2145ef.tar.gz coinosv3-6faf6b6fe49b8e51a38e0106c858341faf2145ef.zip | |
History: a Lightning payment still settling (a zap, mostly) shows at once as a pending Sent row with the recipient's face, and gives way to its completed row
One-tap zaps now record who they went to, so their rows carry a face too.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'tools/ark')
| -rw-r--r-- | tools/ark/ln-pending-history-test.js | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/tools/ark/ln-pending-history-test.js b/tools/ark/ln-pending-history-test.js new file mode 100644 index 0000000..39b59ba --- /dev/null +++ b/tools/ark/ln-pending-history-test.js @@ -0,0 +1,54 @@ +// A Lightning payment still settling (a zap, mostly) shows in history as a +// pending Sent row with the recipient's face, and gives way to the completed +// row once the payment lands. Run: bun tools/ark/ln-pending-history-test.js +import assert from 'node:assert/strict'; + +const { arkFeature } = await import('../../src/features/ark.js'); +const h = (tag, props, ...children) => ({ tag, props, children: children.flat().filter(x => x != null && x !== false) }); +const text = n => n && typeof n === 'object' ? (n.children || []).map(text).join('') : n == null ? '' : String(n); +const store = { zapnotes: {} }; +const ui = {}; +let state; +const feature = arkFeature({ h, ui, render() {}, fmtAmount: String, unitLabel: () => 'sats', unitTag: () => 'sats', goBack() {}, copyBtn: () => null, + hook: (name, pk) => name === 'profileChip' ? h('span', {}, 'face:' + pk.slice(0, 4)) : null, + wallet: { registerCacheExtension() {}, loadArkState: () => state, loadFeatureState: (k, d) => store[k] ?? d, saveFeatureState: (k, v) => { store[k] = v; } } }); + +const zapped = 'c'.repeat(64); +const invoice = 'lnbc210n1zap'; +// what a one-tap zap does before paying: remember whose invoice this is +store.zapnotes['inv:' + invoice] = zapped; +const started = Date.now() - 5000; +const action = { id: `lnpay-${started}`, type: 'ln-pay', step: 'htlc-sent', invoice, paymentHash: 'ab'.repeat(32), amountSat: 21, feeSat: 1, parts: [{ inputId: 'v:0', htlcSat: 22 }] }; +state = { movements: [], actions: [action], vtxos: [] }; + +let rows = feature._histBuild(state); +assert.equal(rows.length, 1, 'the in-flight payment has a row'); +assert.equal(rows[0].time, started, 'dated when it was sent'); +let row = text(rows[0].render()); +assert.match(row, /Sent/); +assert.match(row, /in progress/); +assert.match(row, /-21/, 'shown as money out'); +assert.match(row, /face:cccc/, 'with who was zapped'); +console.log('✓ An in-flight zap shows as a pending Sent row with the recipient'); + +// tapping it opens a detail view while it settles… +ui.arkMoveDetail = 'lnpay:' + action.id; +assert.match(text(feature.historyDetail()), /in progress/); + +// …and once it lands, the completed movement replaces it, row and detail +action.step = 'done'; +state.movements.push({ id: 'mv1', type: 'ln-send', status: 'complete', amountSat: 21, ts: Date.now(), invoice, paymentHash: action.paymentHash, preimage: 'ef'.repeat(32) }); +rows = feature._histBuild(state); +assert.equal(rows.length, 1, 'no duplicate once settled'); +row = text(rows[0].render()); +assert.ok(!/in progress/.test(row), 'the settled row is not pending'); +assert.match(row, /face:cccc/); +const detail = text(feature.historyDetail()); +assert.ok(!/in progress/.test(detail) && /Sent/.test(detail), 'an open detail follows the payment to its completed record'); +console.log('✓ The settled payment replaces the pending row, detail included'); + +// a failed payment leaves no pending row (its failed movement tells it) +const failed = { ...action, id: `lnpay-${started + 1}`, step: 'failed', paymentHash: 'cd'.repeat(32) }; +assert.equal(feature._histBuild({ movements: [], actions: [failed], vtxos: [] }).length, 0); +console.log('✓ A failed payment drops its pending row'); +process.exit(0); |
