Skip to content

fix(kalshi): sync Trade schema with v2 API drift (#1187)#1282

Open
AbhilashG12 wants to merge 2 commits into
pmxt-dev:mainfrom
AbhilashG12:fix/schema-update
Open

fix(kalshi): sync Trade schema with v2 API drift (#1187)#1282
AbhilashG12 wants to merge 2 commits into
pmxt-dev:mainfrom
AbhilashG12:fix/schema-update

Conversation

@AbhilashG12

Copy link
Copy Markdown
Contributor

Closes #1187

What This Does:
Updates the cached OpenAPI spec for Kalshi to resolve the v2 API drift on the Trade schema.

Changes:

  1. Removed taker_side from the required array.
  2. Marked taker_side as deprecated: true per the May 14, 2026 removal deadline.
  3. Added taker_outcome_side (yes | no).
  4. Added taker_book_side (bid | ask).
  5. Added is_block_trade (boolean).

Compiled locally via npm run build --workspace=core; YAML syntax and resulting type generation are clean.

@realfishsam

Copy link
Copy Markdown
Contributor

PR Review: FAIL

What This Does

Updates the vendored Kalshi OpenAPI Trade schema so taker_side is no longer required/deprecated and the newer taker_outcome_side, taker_book_side, and is_block_trade fields are described. This matters because Kalshi trade payload drift can affect fetchTrades consumers.

Blast Radius

Kalshi trade schema/specification only. The runtime Kalshi fetcher/normalizer and generated core/src/exchanges/kalshi/api.ts remain unchanged, so SDK consumers still receive normalized Trade objects through the existing runtime path.

Consumer Verification

Before (base branch):
core/src/exchanges/kalshi/normalizer.ts derives unified trade side only from raw.taker_side:

side: raw.taker_side === 'yes' ? 'buy' : 'sell'

A v2-style payload without taker_side therefore normalizes to sell regardless of taker_outcome_side / taker_book_side.

After (PR branch):
The same consumer/runtime path is still unchanged. I built the PR and exercised the compiled Kalshi normalizer with a v2-style trade payload:

node - <<'NODE'
const { KalshiNormalizer } = require('./core/dist/exchanges/kalshi/normalizer.js');
const n = new KalshiNormalizer();
console.log(JSON.stringify(n.normalizeTrade({
  trade_id:'t1', created_time:'2026-06-22T00:00:00Z',
  yes_price_dollars:'0.42', count_fp:'1.00',
  taker_outcome_side:'yes', taker_book_side:'bid', is_block_trade:false
}, 0)));
NODE

Observed response:

{"id":"t1","timestamp":1782086400000,"price":0.42,"amount":1,"side":"sell"}

So the PR documents the schema drift but does not make the runtime consumer path handle it.

Test Results

  • Build: PASS (npm run build --workspace=pmxt-core)
  • Unit tests: PASS (npm run test --workspace=pmxt-core: 699 passed, 3 skipped)
  • Server starts: NOT VERIFIED (not needed for the schema-only check)
  • E2E smoke: FAIL (focused compiled-normalizer smoke above shows v2 payload is still normalized incorrectly)

Findings

  1. core/src/exchanges/kalshi/normalizer.ts:283normalizeTrade() still computes side from deprecated/non-required raw.taker_side only. With the new Kalshi v2 fields and no taker_side, a taker_outcome_side: "yes" trade normalizes to side: "sell". This is a concrete SDK-consumer-visible failure in fetchTrades; the PR should update the runtime raw type/normalizer (and any relevant tests) to use the new fields safely.
  2. core/src/exchanges/kalshi/api.ts — this generated file still contains no taker_outcome_side, taker_book_side, or is_block_trade references after the YAML edit. If this generated API artifact is committed/used as the runtime Kalshi spec source, the schema regeneration step is incomplete.

PMXT Pipeline Check

  • Field propagation (3-layer): ISSUE — source schema changed, but runtime normalizer/generated Kalshi API artifact did not propagate the new trade fields.
  • OpenAPI sync: N/A — unified PMXT core/src/server/openapi.yaml was not the changed surface.
  • Financial precision: OK — no new arithmetic introduced.
  • Type safety: ISSUE — KalshiRawTrade still requires taker_side even though the PR makes it non-required/deprecated in the venue schema.
  • Auth safety: N/A

Semver Impact

patch -- intended venue API drift compatibility fix.

Risk

Current SDK consumers can still receive incorrect unified trade side values when Kalshi omits deprecated taker_side, despite the spec update.

@AbhilashG12

Copy link
Copy Markdown
Contributor Author

Thanks for clarifying the runtime path! I found the hand-written KalshiRawTrade and KalshiRawFill interfaces in fetcher.ts. I have updated both to make the deprecated fields optional and added the new v2 directional fields (taker_outcome_side, outcome_side, etc.). I then updated normalizer.ts to safely fall back to the new v2 fields if the legacy fields are undefined. The normalizer will now output the correct buy/sell sides regardless of whether it receives a v1 or v2 payload. This should close both #1187 and #1188.

@realfishsam

Copy link
Copy Markdown
Contributor

PR Review: PASS (NOT VERIFIED)

What This Does

Updates the cached Kalshi Trade schema for v2 API drift: taker_side is no longer required/deprecated, and new taker_outcome_side, taker_book_side, and is_block_trade fields are modeled/normalized.

Blast Radius

Kalshi raw fetcher typing, Kalshi trade normalization, and cached Kalshi OpenAPI spec. This affects fetchTrades consumers for Kalshi/Kalshi demo; SDK field survival still depends on the unified trade model/schema accepting the normalized fields.

Consumer Verification

Before (base branch):
The cached Kalshi spec required taker_side, while the PR title/body indicate v2 responses drifted to split taker fields. Without this PR, raw responses lacking taker_side would not match the cached spec and normalized consumers would not receive takerOutcomeSide / takerBookSide / isBlockTrade.

After (PR branch):
Static review shows core/specs/kalshi/Kalshi.yaml makes taker_side optional/deprecated and adds the new v2 fields; core/src/exchanges/kalshi/fetcher.ts types the raw trade fields; core/src/exchanges/kalshi/normalizer.ts forwards them into normalized trade output. I did not call live Kalshi fetchTrades because the review environment has no venue credentials/live fixture for this path.

Test Results

  • Build: PASS (npm run build --workspace=pmxt-core)
  • Unit tests: PASS for targeted available Kalshi normalizer suite: npm test --workspace=pmxt-core -- --runTestsByPath test/normalizers/kalshi-event-title-normalization.test.ts => 8 passed.
  • Server starts: NOT RUN (no live Kalshi credentials for consumer-path fetchTrades smoke)
  • E2E smoke: NOT VERIFIED for live fetchTrades

Findings

No blocking findings.

PMXT Pipeline Check

  • Field propagation (3-layer): NOT VERIFIED. The venue normalizer/spec are updated, but I did not verify generated OpenAPI/SDK shims expose the new normalized trade fields to Python/TypeScript consumers.
  • OpenAPI sync: N/A for PMXT unified OpenAPI; this changes the cached venue spec, not core/src/server/openapi.yaml.
  • Financial precision: OK; no new arithmetic on price/count values.
  • Type safety: OK in changed core files.
  • Auth safety: N/A

Semver Impact

patch -- response-drift compatibility fix for Kalshi trade payloads.

Risk

Consumer-path verification is incomplete: without live/fixture fetchTrades and SDK generated-artifact checks, I could not prove the new fields survive all the way to SDK consumers rather than only the venue-normalizer layer.

@AbhilashG12

AbhilashG12 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

The PR is ready to get merged , as i have tested run test suite locally and confirmed everythings working :

Runtime Verification:

Python:

from pmxt import Kalshi
client = Kalshi(api_key='test', private_key='test')

✅ Import works
✅ Client created

Typescript

import { Kalshi } from 'pmxtjs';
const client = new Kalshi({ apiKey: 'test', privateKey: 'test' });

✅ Import works
✅ Client created

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

spec-drift/kalshi: Trade schema — taker_side deprecated (deadline May 14 2026); taker_outcome_side, taker_book_side, is_block_trade missing

2 participants