Skip to content
markpaper

src/pending/memory.test.ts

v0.2.1 · 3.3 KB

Download file
import { describe, expect, it } from 'vitest';
import { ORDER_ID_A, ORDER_ID_B } from '../testing/fixtures.js';
import {
  applyPendingToRead,
  createPendingMemory,
  DEFAULT_ECHO_TTL_MS,
  DEFAULT_FAR_FROM_MARK_TTL_MS,
  placeKey,
} from './memory.js';

describe('placeKey', () => {
  it('is coin + side + price string, without size', () => {
    expect(placeKey('ETH', true, '1650.00')).toBe('ETH|B|1650.00');
    expect(placeKey('ETH', false, '1650.00')).toBe('ETH|A|1650.00');
    // the same order with a different size is the same key: that is the point
    expect(placeKey('ETH', true, '1650.00')).toBe(placeKey('ETH', true, '1650.00'));
  });
});

describe('createPendingMemory', () => {
  it('remembers a placed key for the echo TTL and forgets it when it shows up', () => {
    const m = createPendingMemory();
    const t0 = 1_000_000;
    const key = placeKey('ETH', true, '1650.00');
    m.notePlaced(key, t0);
    expect(m.isPlaced(key, t0 + 1)).toBe(true);
    expect(m.isPlaced(key, t0 + DEFAULT_ECHO_TTL_MS - 1)).toBe(true);
    expect(m.isPlaced(key, t0 + DEFAULT_ECHO_TTL_MS)).toBe(false);
    m.notePlaced(key, t0);
    m.forgetPlaced(key);
    expect(m.isPlaced(key, t0 + 1)).toBe(false);
  });

  it('remembers a confirmed cancel by exact id', () => {
    const m = createPendingMemory({ echoTtlMs: 100 });
    m.noteCancelled(ORDER_ID_A, 0);
    expect(m.isCancelled(ORDER_ID_A, 50)).toBe(true);
    expect(m.isCancelled(ORDER_ID_B, 50)).toBe(false); // rounds to the same double, but the memory is by string
    expect(m.isCancelled(ORDER_ID_A, 100)).toBe(false);
  });

  it('remembers a far-from-mark key for minutes, longer than the echo', () => {
    const m = createPendingMemory();
    const key = placeKey('X', true, '0.0200');
    m.noteFarFromMark(key, 0);
    expect(m.isFarFromMark(key, DEFAULT_ECHO_TTL_MS + 1)).toBe(true);
    expect(m.isFarFromMark(key, DEFAULT_FAR_FROM_MARK_TTL_MS - 1)).toBe(true);
    expect(m.isFarFromMark(key, DEFAULT_FAR_FROM_MARK_TTL_MS)).toBe(false);
  });

  it('uses the injected clock and reports counts', () => {
    let t = 0;
    const m = createPendingMemory({ echoTtlMs: 10, farFromMarkTtlMs: 20, now: () => t });
    m.notePlaced('a');
    m.noteCancelled('1');
    m.noteFarFromMark('b');
    expect(m.counts()).toEqual({ placed: 1, cancelled: 1, farFromMark: 1 });
    t = 10;
    expect(m.counts()).toEqual({ placed: 0, cancelled: 0, farFromMark: 1 });
    t = 20;
    expect(m.counts()).toEqual({ placed: 0, cancelled: 0, farFromMark: 0 });
    m.notePlaced('a');
    m.reset();
    expect(m.counts()).toEqual({ placed: 0, cancelled: 0, farFromMark: 0 });
  });
});

describe('applyPendingToRead', () => {
  it('strikes out confirmed cancels and releases placed keys that appeared', () => {
    const m = createPendingMemory({ echoTtlMs: 1000 });
    const seen = { orderId: ORDER_ID_A, coin: 'ETH', isBuy: true, priceStr: '1650.00' };
    const gone = { orderId: ORDER_ID_B, coin: 'ETH', isBuy: false, priceStr: '1700.00' };
    m.notePlaced(placeKey('ETH', true, '1650.00'), 0);
    m.notePlaced(placeKey('ETH', true, '1600.00'), 0); // not yet in the book
    m.noteCancelled(ORDER_ID_B, 0);
    const out = applyPendingToRead([seen, gone], m, 1);
    expect(out).toEqual([seen]);
    expect(m.isPlaced(placeKey('ETH', true, '1650.00'), 1)).toBe(false);
    expect(m.isPlaced(placeKey('ETH', true, '1600.00'), 1)).toBe(true);
  });
});
All files