src/testing/fixtures.ts
v0.1.0 · 3.8 KB
// 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,
};