|
| 1 | +const test = require('node:test'); |
| 2 | +const assert = require('node:assert'); |
| 3 | +const { applyCloseTrade, applyImportedTrades } = require('../../src/js/18b-chain-apply.js'); |
| 4 | + |
| 5 | +const PAST_DATE = '2020-01-01'; |
| 6 | +const FUTURE_DATE = '2099-12-31'; |
| 7 | + |
| 8 | +// ── applyCloseTrade ────────────────────────────────────────────────────────── |
| 9 | + |
| 10 | +test('applyCloseTrade: matches OPEN trade and sets CLOSED + closeCost', () => { |
| 11 | + const arr = [ |
| 12 | + { id: 1, asset: 'HYPE', type: 'PUT', expiry: '2026-05-01', strike: 30, premium: 10, outcome: 'OPEN' }, |
| 13 | + ]; |
| 14 | + const result = applyCloseTrade(arr, { asset: 'HYPE', type: 'PUT', expiry: '2026-05-01', strike: 30, premium: 3 }); |
| 15 | + assert.strictEqual(result, true); |
| 16 | + assert.strictEqual(arr[0].outcome, 'CLOSED'); |
| 17 | + assert.strictEqual(arr[0].closeCost, 3); |
| 18 | +}); |
| 19 | + |
| 20 | +test('applyCloseTrade: no match on strike → returns false, no mutation', () => { |
| 21 | + const arr = [ |
| 22 | + { id: 1, asset: 'HYPE', type: 'PUT', expiry: '2026-05-01', strike: 30, premium: 10, outcome: 'OPEN' }, |
| 23 | + ]; |
| 24 | + const result = applyCloseTrade(arr, { asset: 'HYPE', type: 'PUT', expiry: '2026-05-01', strike: 35, premium: 3 }); |
| 25 | + assert.strictEqual(result, false); |
| 26 | + assert.strictEqual(arr[0].outcome, 'OPEN'); |
| 27 | +}); |
| 28 | + |
| 29 | +test('applyCloseTrade: non-OPEN trade is not matched', () => { |
| 30 | + const arr = [ |
| 31 | + { id: 1, asset: 'HYPE', type: 'PUT', expiry: '2026-05-01', strike: 30, premium: 10, outcome: 'EXPIRED' }, |
| 32 | + ]; |
| 33 | + const result = applyCloseTrade(arr, { asset: 'HYPE', type: 'PUT', expiry: '2026-05-01', strike: 30, premium: 3 }); |
| 34 | + assert.strictEqual(result, false); |
| 35 | +}); |
| 36 | + |
| 37 | +// ── applyImportedTrades ────────────────────────────────────────────────────── |
| 38 | + |
| 39 | +test('applyImportedTrades: pushes open trade and strips isClose field', () => { |
| 40 | + const arr = []; |
| 41 | + const synced = new Set(); |
| 42 | + const open = [{ id: 1, asset: 'HYPE', type: 'PUT', expiry: FUTURE_DATE, outcome: 'OPEN', isClose: false, txHash: 'tx1' }]; |
| 43 | + const { added } = applyImportedTrades(arr, open, [], synced); |
| 44 | + assert.strictEqual(added, 1); |
| 45 | + assert.strictEqual(arr.length, 1); |
| 46 | + assert.strictEqual('isClose' in arr[0], false, 'isClose must be stripped from pushed trade'); |
| 47 | + assert.ok(synced.has('tx1')); |
| 48 | +}); |
| 49 | + |
| 50 | +test('applyImportedTrades: already-synced txHash is skipped', () => { |
| 51 | + const arr = []; |
| 52 | + const synced = new Set(['tx1']); |
| 53 | + const open = [{ id: 1, asset: 'HYPE', type: 'PUT', expiry: FUTURE_DATE, outcome: 'OPEN', isClose: false, txHash: 'tx1' }]; |
| 54 | + const { added } = applyImportedTrades(arr, open, [], synced); |
| 55 | + assert.strictEqual(added, 0); |
| 56 | + assert.strictEqual(arr.length, 0); |
| 57 | +}); |
| 58 | + |
| 59 | +test('applyImportedTrades: close trade matches open → CLOSED, closedCount: 1', () => { |
| 60 | + const arr = [ |
| 61 | + { id: 1, asset: 'HYPE', type: 'PUT', expiry: '2026-05-01', strike: 30, premium: 10, outcome: 'OPEN' }, |
| 62 | + ]; |
| 63 | + const synced = new Set(); |
| 64 | + const close = [{ asset: 'HYPE', type: 'PUT', expiry: '2026-05-01', strike: 30, premium: 3, isClose: true, txHash: 'tx-c' }]; |
| 65 | + const { closedCount } = applyImportedTrades(arr, [], close, synced); |
| 66 | + assert.strictEqual(closedCount, 1); |
| 67 | + assert.strictEqual(arr[0].outcome, 'CLOSED'); |
| 68 | + assert.strictEqual(arr[0].closeCost, 3); |
| 69 | + assert.ok(synced.has('tx-c')); |
| 70 | +}); |
| 71 | + |
| 72 | +test('applyImportedTrades: unknown close trade with no match → closedCount: 0', () => { |
| 73 | + const arr = []; |
| 74 | + const synced = new Set(); |
| 75 | + const close = [{ asset: 'HYPE', type: 'PUT', expiry: '2026-05-01', strike: 99, premium: 3, isClose: true, txHash: 'tx-c' }]; |
| 76 | + const { closedCount } = applyImportedTrades(arr, [], close, synced); |
| 77 | + assert.strictEqual(closedCount, 0); |
| 78 | +}); |
| 79 | + |
| 80 | +test('applyImportedTrades: OPEN RYSK trade with past expiry corrected to EXPIRED', () => { |
| 81 | + const arr = [ |
| 82 | + { id: 1, asset: 'HYPE', type: 'PUT', expiry: PAST_DATE, outcome: 'OPEN', platform: 'RYSK' }, |
| 83 | + ]; |
| 84 | + const { corrected } = applyImportedTrades(arr, [], [], new Set()); |
| 85 | + assert.strictEqual(corrected, 1); |
| 86 | + assert.strictEqual(arr[0].outcome, 'EXPIRED'); |
| 87 | +}); |
| 88 | + |
| 89 | +test('applyImportedTrades: OPEN HSFC trade with past expiry corrected to EXPIRED', () => { |
| 90 | + const arr = [ |
| 91 | + { id: 1, asset: 'HYPE', type: 'PUT', expiry: PAST_DATE, outcome: 'OPEN', platform: 'HSFC' }, |
| 92 | + ]; |
| 93 | + const { corrected } = applyImportedTrades(arr, [], [], new Set()); |
| 94 | + assert.strictEqual(corrected, 1); |
| 95 | + assert.strictEqual(arr[0].outcome, 'EXPIRED'); |
| 96 | +}); |
| 97 | + |
| 98 | +test('applyImportedTrades: OPEN trade with future expiry is not corrected', () => { |
| 99 | + const arr = [ |
| 100 | + { id: 1, asset: 'HYPE', type: 'PUT', expiry: FUTURE_DATE, outcome: 'OPEN', platform: 'RYSK' }, |
| 101 | + ]; |
| 102 | + const { corrected } = applyImportedTrades(arr, [], [], new Set()); |
| 103 | + assert.strictEqual(corrected, 0); |
| 104 | + assert.strictEqual(arr[0].outcome, 'OPEN'); |
| 105 | +}); |
0 commit comments