aboutsummaryrefslogtreecommitdiffstats
path: root/tools/ln-receive-twin-test.js
blob: 20d4f482ae6251340cdff6a0063a2b26bc19c99e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// One Lightning receive, told twice: the claim's ln-receive and the mailbox's
// plain receive of the same coin (The Daniel: two "Received 1,005" rows and a
// 2,010 celebration). lnFoldedIds names the twin; nothing else is folded.
// Run: bun tools/ln-receive-twin-test.js
import { lnFoldedIds } from '../src/ark/manager.js';
let ok = true;
const check = (n, c, d = '') => { console.log(` ${c ? '✓' : '✗'} ${n}${d ? ' — ' + d : ''}`); if (!c) ok = false; };
const T = 1_790_000_000_000;
const rcv = (id, sat, ts, extra = {}) => ({ id, type: 'receive', status: 'complete', amountSat: sat, ts, vtxoId: 'v-' + id, ...extra });
const ln = (id, sat, ts, extra = {}) => ({ id, type: 'ln-receive', status: 'complete', amountSat: sat, ts, ...extra });

let f = lnFoldedIds([ln('L', 1005, T, { vtxoIds: ['v-R'] }), rcv('R', 1005, T + 900)]);
check('a claim stamped with its coin folds the mailbox\'s receive of it', f.has('R') && f.size === 1);
f = lnFoldedIds([rcv('R', 1005, T - 400), ln('L', 1005, T, { vtxoIds: ['v-R'] })]);
check('...whichever came first', f.has('R'));
f = lnFoldedIds([ln('L', 1005, T, { vtxoIds: ['v-X'] }), rcv('R', 1005, T + 900)]);
check('a stamped claim never folds some other coin of the same amount', f.size === 0);
f = lnFoldedIds([ln('L', 1005, T), rcv('R', 1005, T + 60_000)]);
check('an unstamped (older) claim folds the same amount within minutes', f.has('R'));
f = lnFoldedIds([ln('L', 1005, T), rcv('R', 1005, T + 30 * 60_000)]);
check('...not half an hour apart', f.size === 0);
f = lnFoldedIds([ln('L', 1005, T), rcv('R', 1006, T + 1000)]);
check('...nor a different amount', f.size === 0);
f = lnFoldedIds([ln('L', 1005, T), rcv('R', 1005, T + 1000, { viaLn: true })]);
check('...nor a name@ receive the registrar\'s receipts claimed', f.size === 0);
f = lnFoldedIds([ln('L1', 500, T), ln('L2', 500, T + 5000), rcv('R1', 500, T + 1000), rcv('R2', 500, T + 6000)]);
check('two claims of one amount fold one receive each', f.has('R1') && f.has('R2') && f.size === 2);
f = lnFoldedIds([rcv('R', 1005, T), rcv('S', 2000, T)]);
check('plain receives with no claim stay', f.size === 0);
// the same coin recorded by two devices (each its own movement id), one of
// them tagged ⚡ by the registrar's receipts: one row, the tagged one
f = lnFoldedIds([rcv('A', 1000, T), { ...rcv('B', 1000, T + 2000), vtxoId: 'v-A', viaLn: true }, { ...rcv('C', 1000, T + 3000), vtxoId: 'v-A' }, { ...rcv('D', 1000, T + 4000), vtxoId: 'v-A', viaLn: true }]);
check('one coin recorded four times shows once, the ⚡ copy', f.size === 3 && !f.has('B'), [...f].join(','));
f = lnFoldedIds([rcv('A', 1000, T), { ...rcv('B', 1000, T + 2000), vtxoId: 'v-A' }]);
check('...or the earliest when none is tagged', f.size === 1 && f.has('B'));
f = lnFoldedIds([rcv('A', 1000, T), rcv('B', 1000, T + 2000)]);
check('two coins of the same amount stay two rows', f.size === 0);
console.log(ok ? '\n✅ a claimed LN receive is told once' : '\n❌ failed');
process.exit(ok ? 0 : 1);