Skip to content
markpaper

src/testing/fixtures.ts

v0.1.0 · 3.8 KB

Download file
// Synthetic fixtures only. Every account identity is generated; amounts are invented.
import { randomBytes } from 'node:crypto';
import { base58Decode, base58Encode } from '../address/base58.js';
import { GLOBAL_CONFIG_DISCRIMINANT, GLOBAL_CONFIG_LAYOUT, GLOBAL_CONFIGURATION } from '../onchain/global.js';
import { TRADER_DISCRIMINANT, TRADER_HEADER } from '../onchain/header.js';

export const owner = base58Encode(randomBytes(32));
export const delegate = base58Encode(randomBytes(32));
export const pda = base58Encode(randomBytes(32));
export const signature = base58Encode(randomBytes(64));
export const exchangeKeys = {
  globalConfig: GLOBAL_CONFIGURATION,
  perpAssetMap: base58Encode(randomBytes(32)),
  globalTraderIndex: [base58Encode(randomBytes(32))],
  activeTraderBuffer: [base58Encode(randomBytes(32))],
};
export function market(symbol = 'BTC', assetId = 1) {
  return {
    symbol,
    assetId,
    marketStatus: 'active',
    tickSize: 100,
    baseLotsDecimals: 4,
    isolatedOnly: false,
    leverageTiers: [{ maxLeverage: 10 }],
    marketPubkey: base58Encode(randomBytes(32)),
    splinePubkey: base58Encode(randomBytes(32)),
  };
}
export const token = (ui: string) => ({ ui, value: '0', decimals: 6 });
export function state(lots = '3', slot = 100) {
  return {
    authority: owner,
    traderPdaIndex: 0,
    slot,
    snapshot: {
      capabilities: { state: 'cold' },
      subaccounts: [
        {
          subaccountIndex: 0,
          collateral: '70000000',
          positions:
            lots === '0'
              ? []
              : [{ symbol: 'BTC', basePositionLots: lots, entryPriceTicks: '800', entryPriceUsd: '800' }],
          orders: [],
        },
      ],
    },
  };
}
export function view(size = '0.0003', slot = 100) {
  return {
    authority: owner,
    traderKey: pda,
    traderPdaIndex: 0,
    traderSubaccountIndex: 0,
    slot,
    portfolioValue: token('72'),
    riskState: 'healthy',
    initialMargin: token('4'),
    effectiveCollateral: token('70'),
    positions:
      size === '0'
        ? []
        : [
            {
              symbol: 'BTC',
              positionSize: token(size),
              positionValue: token('0.24'),
              unrealizedPnl: token('2'),
              positionInitialMargin: token('0.024'),
            },
          ],
  };
}
export function headerBytes(flags = 62, prefs = 0) {
  const d = new Uint8Array(TRADER_HEADER.LEN);
  d.set(TRADER_DISCRIMINANT);
  d.set(base58Decode(owner)!, TRADER_HEADER.AUTHORITY);
  d.set(base58Decode(delegate)!, TRADER_HEADER.POSITION_AUTHORITY);
  const dv = new DataView(d.buffer);
  dv.setBigInt64(TRADER_HEADER.COLLATERAL, 70000000n, true);
  dv.setUint32(TRADER_HEADER.FLAGS, flags, true);
  dv.setUint32(TRADER_HEADER.MAX_POSITIONS, 16, true);
  dv.setUint32(TRADER_HEADER.PREFS, prefs, true);
  return d;
}
export function globalBytes(flags = 1) {
  const d = new Uint8Array(GLOBAL_CONFIG_LAYOUT.LEN);
  d.set(GLOBAL_CONFIG_DISCRIMINANT);
  for (const [off, k] of [
    [GLOBAL_CONFIG_LAYOUT.ACCOUNT_KEY, exchangeKeys.globalConfig],
    [GLOBAL_CONFIG_LAYOUT.PERP_ASSET_MAP, exchangeKeys.perpAssetMap],
    [GLOBAL_CONFIG_LAYOUT.GTI_HEADER, exchangeKeys.globalTraderIndex[0]!],
    [GLOBAL_CONFIG_LAYOUT.ATB_HEADER, exchangeKeys.activeTraderBuffer[0]!],
  ] as const)
    d.set(base58Decode(k)!, off);
  d[GLOBAL_CONFIG_LAYOUT.QUOTE_DECIMALS] = 6;
  d[GLOBAL_CONFIG_LAYOUT.SPOT_FLAGS] = flags;
  return d;
}
export const memoryPolicy = {
  maxReadLagSlots: 10,
  uncertainFillGateMs: 100,
  echoTtlMs: 200,
  iocSlotTtl: 5,
  signWindowMs: 10,
  slotMsCeil: 2,
  noResponseLockSlots: 3,
  noResponseLockMs: 40,
  noResponseLockGtcMs: 60,
  bandRejectTtlMs: 20,
  bandAfterHoursMaxMs: 100,
};
export const restPolicy = {
  minGapMs: 0,
  tries: 2,
  timeoutMs: 1000,
  retryDelayMs: 0,
  retryAfterMaxMs: 5000,
  retryAfterFallbackMs: 100,
};
All files