const test = require('node:test'); const assert = require('node:assert'); const L = require('../ladder'); const own = new Set(['nano_own']); const src = (account, last_at) => ({ account, amount_raw: '1', first_at: last_at, last_at, receives: [{ at: last_at, amount_raw: '1', hash: 'H' }] }); test('operator paid the source before its transfer: in order', () => { const r = L.inOrderFunding([src('nano_a', '2026-09-15T07:25:33.000Z')], own, () => [{ ts: '2026-09-15T04:33:25.678Z', kind: 'other' }]); assert.deepStrictEqual([r.any, r.excluding_ladder_returns], [true, true]); }); test('operator paid the source only after its transfer: not in order, even though the original field would fire', () => { const r = L.inOrderFunding([src('nano_a', '2026-09-15T07:25:33.000Z')], own, () => [{ ts: '2026-09-16T00:00:00.000Z', kind: 'other' }]); assert.deepStrictEqual([r.any, r.excluding_ladder_returns], [false, false]); }); test('only a ladder payout before the transfer: in order for any, not for excluding_ladder_returns', () => { const r = L.inOrderFunding([src('nano_a', '2026-09-15T07:25:33.000Z')], own, () => [{ ts: '2026-09-15T00:00:00.000Z', kind: 'ladder_payout' }]); assert.deepStrictEqual([r.any, r.excluding_ladder_returns], [true, false]); }); test('own address source is in order; unreadable ledger is null; no sources is false; missing receives is null', () => { assert.strictEqual(L.inOrderFunding([src('nano_own', '2026-09-15T00:00:00.000Z')], own, () => []).any, true); const o = L.inOrderFunding([src('nano_own', '2026-09-15T00:00:00.000Z')], own, () => [], () => false); assert.deepStrictEqual([o.any, o.excluding_ladder_returns], [true, false]); assert.strictEqual(L.inOrderFunding([src('nano_a', '2026-09-15T00:00:00.000Z')], own, () => null).any, null); assert.strictEqual(L.inOrderFunding([], own, () => []).any, false); assert.strictEqual(L.inOrderFunding(null, own, () => []).any, null); assert.strictEqual(L.inOrderFunding([{ account: 'nano_a', amount_raw: '1', first_at: '2026-09-15T00:00:00.000Z' }], own, () => [{ ts: '2026-09-14T00:00:00.000Z', kind: 'other' }]).any, null); }); test('payment kinds list is closed and versioned', () => { assert.strictEqual(L.PAYMENT_KINDS.version, 1); assert.deepStrictEqual(Object.keys(L.PAYMENT_KINDS.kinds).sort(), ['ladder_payout', 'ladder_refund', 'other']); assert.strictEqual(L.paymentKind('Ladder round 1 payout to rank 1'), 'ladder_payout'); assert.strictEqual(L.paymentKind('Seller credit'), 'other'); });