aboutsummaryrefslogtreecommitdiffstats
path: root/tools/ark-htlc-orphan.test.js
blob: cc127be7bcc372cefe49e4e0fe718188e790e92a (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
// bun test tools/ark-htlc-orphan.test.js — an HTLC coin whose payment's
// action has been pruned is an orphan the server settles: spent means spent
// (it stopped counting as pending money), still-open stays pending, and a
// coin a live payment holds is never asked about.
import { test, expect, mock } from 'bun:test';
import * as proto from '../src/ark/proto.js';
const asked = [];
mock.module('../src/ark/proto.js', () => ({ ...proto, getVtxoStatus: async (url, raw) => { asked.push(raw[0]); return raw[0] === 1 ? proto.VTXO_STATE_SPENT : proto.VTXO_STATE_SPENDABLE; } }));
const { ArkManager } = await import('../src/ark/manager.js');
test('orphan HTLC coins are settled by the server\'s answer', async () => {
  const m = Object.create(ArkManager.prototype);
  m.state = {
    vtxos: [
      { id: 'gone', state: 'pending', amountSat: 22, bytes: 'x', policy: 'serverHtlcSend', tag: 1 },   // payment done long ago, action pruned: server says spent
      { id: 'open', state: 'pending', amountSat: 22, bytes: 'x', policy: 'serverHtlcSend', tag: 2 },   // orphan the server still holds open
      { id: 'held', state: 'pending', amountSat: 22, bytes: 'x', policy: 'serverHtlcSend', tag: 3 },   // a live payment's: not asked about
      { id: 'coin', state: 'pending', amountSat: 500, bytes: 'x', policy: 'pubkey', tag: 2 },          // a plain orphan the server counts: spendable again
    ],
    actions: [{ type: 'ln-pay', step: 'initiated', parts: [{ inputId: 'in1' }], htlcVtxoIds: ['held'] }],
    scheduled: [],
  };
  m.arkUrl = 'x';
  m._decoded = (v) => ({ point: { raw: Uint8Array.of(v.tag) }, policy: { type: v.policy } });
  m._keyForVtxo = () => ({ privkey: new Uint8Array(32) });
  m._save = () => {}; m._movement = () => {}; m._remoteBusy = () => new Set();
  await m.reconcile();
  const st = Object.fromEntries(m.state.vtxos.map((v) => [v.id, v.state]));
  expect(st.gone).toBe('spent');
  expect(st.open).toBe('pending');
  expect(st.held).toBe('pending');
  expect(st.coin).toBe('spendable');
  expect(asked.sort()).toEqual([1, 2, 2]);
});