Skip to content

V1 order request models miss ge=0 on subaccount/exchange_index that V2 and other models enforce #326

Closed

Description

@TexasCoding

Problem

Every V2 request model, the communications/order_groups request models, and the subaccount-transfer body enforce ge=0 on subaccount-shaped integer fields. The V1 order family — CreateOrderRequest, AmendOrderRequest, DecreaseOrderRequest, BatchCancelOrdersRequestOrder — uses bare StrictInt | None with no lower-bound constraint. A caller passing subaccount=-1 or exchange_index=-7 to V1 constructs cleanly, the SDK signs the request, and the server rejects with 400.

This undermines the invariant the docstring on ApplySubaccountTransferRequest calls out — that subaccount fields validate the lower bound so server-assigned numbers always round-trip. v2.6's #295 already retro-fitted StrictInt to these same fields, so they were touched once; adding ge=0 is the same one-line shape.

Evidence

  • kalshi/models/orders.py:194-195 (V1 CreateOrderRequest — bare StrictInt | None):
subaccount: StrictInt | None = None
exchange_index: StrictInt | None = None
  • kalshi/models/orders.py:269-270, 291-292, 335-336 — same pattern in AmendOrderRequest, DecreaseOrderRequest, BatchCancelOrdersRequestOrder.
  • kalshi/models/orders.py:482 (V2 CreateOrderV2Request enforces it):
subaccount: StrictInt | None = Field(default=None, ge=0)
  • kalshi/models/orders.py:625 (BatchCancelOrdersV2RequestOrder), kalshi/models/communications.py:160, kalshi/models/order_groups.py:59, kalshi/models/subaccounts.py:34 — all use Field(..., ge=0).
  • Note: CreateOrderV2Request.exchange_index at kalshi/models/orders.py:484 and BatchCancelOrdersV2RequestOrder.exchange_index at :626 are also bare StrictInt | None, so the parity fix should sweep those too.

Suggested fix

Replace bare declarations with Field(default=None, ge=0) on every subaccount-shaped int across the V1 order models and the two V2 exchange_index slots that were missed:

  • CreateOrderRequest.subaccount, CreateOrderRequest.exchange_index
  • AmendOrderRequest.subaccount, AmendOrderRequest.exchange_index
  • DecreaseOrderRequest.subaccount, DecreaseOrderRequest.exchange_index
  • BatchCancelOrdersRequestOrder.subaccount, BatchCancelOrdersRequestOrder.exchange_index
  • CreateOrderV2Request.exchange_index
  • BatchCancelOrdersV2RequestOrder.exchange_index

Extend tests/test_models.py's negative-value coverage (which today only exercises V2 + communications) to these classes.

Source

Round-3 independent audit (reviewer: models_contracts).

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions