Risk Level
HIGH
File
core/src/exchanges/kalshi/normalizer.ts
Findings
- Line 128–130:
(p as any)[field], (ask as any)[field], (bid as any)[field] — dynamic field access via as any on order book entries; TypeScript cannot verify these fields exist
- Line 135:
(p as any).previous || 0 — accessing .previous via as any
- Line 287:
private deriveEventDescription(markets: any[]): string — array of markets typed as any[] in a normalizer method
- Line 357:
function eventVolume(event: any): number — module-level utility function with any parameter
- Line 358:
(event.markets || []).reduce((sum: number, m: any) => ...) — markets map elements untyped
- Line 361:
function eventLiquidity(event: any): number — same pattern
- Line 362:
(event.markets || []).reduce((sum: number, m: any) => ...) — same
- Line 365:
function eventNewest(event: any): number — same pattern
- Line 367:
.map((m: any) => ...) — markets map element untyped
- Line 372:
export function sortRawEvents(events: any[], sort: string): any[] — exported function with any[] params and return
Impact
sortRawEvents(events: any[], sort: string): any[] is exported — any caller receives any[] back, losing type information on every event it processes
- Dynamic field access
(p as any)[field] on order book entries means a typo in field goes undetected at compile time
- All three utility functions (
eventVolume, eventLiquidity, eventNewest) accept any — they could silently receive the wrong data shape
Suggested Fix
- Define
KalshiRawEvent and KalshiRawMarket interfaces matching the Kalshi API wire format
- Replace
sortRawEvents(events: any[], ...): any[] with sortRawEvents(events: KalshiRawEvent[], ...): KalshiRawEvent[]
- Use a typed index signature on the order book entry interface instead of
(p as any)[field]
Found by automated any type audit
Risk Level
HIGH
File
core/src/exchanges/kalshi/normalizer.tsFindings
(p as any)[field],(ask as any)[field],(bid as any)[field]— dynamic field access viaas anyon order book entries; TypeScript cannot verify these fields exist(p as any).previous || 0— accessing.previousviaas anyprivate deriveEventDescription(markets: any[]): string— array of markets typed asany[]in a normalizer methodfunction eventVolume(event: any): number— module-level utility function withanyparameter(event.markets || []).reduce((sum: number, m: any) => ...)— markets map elements untypedfunction eventLiquidity(event: any): number— same pattern(event.markets || []).reduce((sum: number, m: any) => ...)— samefunction eventNewest(event: any): number— same pattern.map((m: any) => ...)— markets map element untypedexport function sortRawEvents(events: any[], sort: string): any[]— exported function withany[]params and returnImpact
sortRawEvents(events: any[], sort: string): any[]is exported — any caller receivesany[]back, losing type information on every event it processes(p as any)[field]on order book entries means a typo infieldgoes undetected at compile timeeventVolume,eventLiquidity,eventNewest) acceptany— they could silently receive the wrong data shapeSuggested Fix
KalshiRawEventandKalshiRawMarketinterfaces matching the Kalshi API wire formatsortRawEvents(events: any[], ...): any[]withsortRawEvents(events: KalshiRawEvent[], ...): KalshiRawEvent[](p as any)[field]Found by automated any type audit