feat(kalshi): /v1/kalshi/* endpoints - #559
Open
0237h wants to merge 1 commit into
Open
Conversation
Adds six endpoints under /v1/kalshi/ backed by the substreams-kalshi v0.4.0 schema (state_platform + state_ohlcv_trades_by_series rollups plus expiration_value as Nullable(Float64)): - GET /v1/kalshi/markets — settled-market snapshots - GET /v1/kalshi/markets/trades — fill-by-fill history (filter required) - GET /v1/kalshi/markets/ohlc — 1m/1h/1d OHLCV bars per ticker - GET /v1/kalshi/markets/settlement — canonical resolution records - GET /v1/kalshi/series — series leaderboard via state_ohlcv_trades_by_series - GET /v1/kalshi/platform — platform-wide aggregate via state_platform Wiring: - dbsConfig: `kalshi` added to the network-type enum and a `kalshiDatabases` map alongside the existing per-type maps. - routes/index: `cacheControl()` applied to /v1/kalshi/*; the six routes mounted in path-specificity order. - zod: kalshiTickerSchema (accepts `.` for strike values), kalshiSeriesSchema, kalshiEventTickerSchema, kalshiIntervalSchema (1m / 1h / 1d — Kalshi's native /markets/candlesticks granularities), kalshiMarketStatusSchema. Notable design calls: - Decimals returned as z.number() (matches polymarket / hyperliquid OHLCV); the µs trade timestamp is the one exception — z.string() per the BigInt-as-string precedent, since 16-digit microseconds-since-epoch will approach JS Number.MAX_SAFE_INTEGER in time. - /platform and /series read state_platform / state_ohlcv_trades_by_series with SETTINGS optimize_aggregation_in_order = 1 — the GROUP BY matches the source AggregatingMergeTree sort key prefix. - /markets/trades requires at least one of ticker / series / start_time (mirrors polymarket activity); returns 400 bad_query_input otherwise. - series_from_ticker(ticker) — the ClickHouse function defined in the substreams schema — is used in ohlc.sql and settlement.sql instead of inline splitByChar, so the parsing rule stays single-sourced. - markets.expiration_value goes through toFloat64OrNull(toString(...)) so the same SQL works against both the legacy String column and the v0.4.0 Nullable(Float64) shape — no follow-up needed once dev1 catches up. Test coverage in routes.sql.spec.ts adds 15 cases mirroring the hyperliquid / polymarket coverage: per-endpoint smoke, key filter combinations, error paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds six endpoints under
/v1/kalshi/*backed by the substreams-kalshi v0.4.0 schema:GET /v1/kalshi/marketsmarkets(RMT)GET /v1/kalshi/markets/tradestradesticker/series/start_timeGET /v1/kalshi/markets/ohlcohlcv_tradesviewGET /v1/kalshi/markets/settlementmarket_lifecycleGET /v1/kalshi/seriesstate_ohlcv_trades_by_seriesGET /v1/kalshi/platformohlcv_platformviewPlus the network-type wiring:
dbsConfigacceptstype: kalshiand exposeskalshiDatabases, the routes mount under/v1/kalshi/*withcacheControl(), and 15 cases land inroutes.sql.spec.tsfor per-endpoint smoke + filter combinations + error paths.Why
Kalshi is Phase 1 of the prediction-markets roadmap. The substreams pipeline (firehose-kalshi → substreams-kalshi → sink-sql) produces the schema this PR consumes — v0.4.0 added the
state_platform+state_ohlcv_trades_by_seriesrollups so/platformand/seriesserve flat reads instead of fanning out across every ticker bar at query time.Code references
src/types/zod.ts—kalshiTickerSchema(accepts.for strike values likeKXBTCD-26APR3020-T76299.99),kalshiSeriesSchema,kalshiEventTickerSchema,kalshiIntervalSchema(1m/1h/1d),kalshiMarketStatusSchema.src/config/dbsConfig.ts—'kalshi'added to the network-type enum andkalshiDatabasestoParsedDbsConfig.src/routes/kalshi/— six route handlers + SQL files.src/routes/index.ts—/v1/kalshi/*mounts.src/routes/routes.sql.spec.ts— kalshi suite under the existingSQL queriesdescribe block.Design calls worth flagging:
z.number()(matches polymarket / hyperliquid OHLCV). The exception istrades.timestamp_us— stringified, because 16-digit microseconds-since-epoch eventually approachesNumber.MAX_SAFE_INTEGER. Same precedent as polymarket's UInt256amountfield.series_from_ticker(ticker)— the ClickHouse function defined in the substreams schema — is used inohlc.sqlandsettlement.sqlinstead of inlinesplitByChar, so the parsing rule stays single-sourced./markets/tradesrequires at least one ofticker/series/start_time(returns 400bad_query_inputotherwise) — mirrors polymarket activity, avoids an unbounded full-table sort./platformand/seriesuseSETTINGS optimize_aggregation_in_order = 1since their GROUP BY matches the source AggregatingMergeTree sort-key prefix.markets.expiration_valuegoes throughtoFloat64OrNull(toString(...))— works against both the legacyStringcolumn and the v0.4.0Nullable(Float64)column, so no follow-up is needed once dev1 catches up.🤖 Generated with Claude Code