Releases: pinax-network/pinax-api
Release list
v3.21.1
Performance release: pool OHLC queries no longer scan a pool's full history to return a page of candles. Responses are byte-identical to before — this is a pure query-planning change with no API, parameter, or schema changes.
Performance
Pool OHLC endpoints — bounded to the requested window (#583)
GET /v1/svm/pools/ohlc, /v1/evm/pools/ohlc, and /v1/tvm/pools/ohlc aggregate AggregateFunction state rows with a blocking GROUP BY. Without a lower time bound, ClickHouse had to merge a pool's entire history before ORDER BY … LIMIT could discard all but the requested page. On high-activity pools this read gigabytes and used gigabytes of RAM per request, producing multi-second latencies and intermittent 500s under concurrency (reported in #582).
Each query now first derives the timestamp cutoff of the most-recent limit + offset candles by scanning only the cheap timestamp column, then constrains the heavy aggregation to that window. Sparse pools (whose candles span a much wider wall-clock range than interval × limit) return exactly the same rows as before — the cutoff is derived from the data, not a fixed lookback.
Measured on production against the outlier pools from #582:
| Query | Before | After |
|---|---|---|
SVM 1m / limit 60 |
830–1240 ms · 210 MiB read · ~815 MiB RAM | 120–200 ms · 16 MiB · ~42 MiB |
SVM 5m / limit 288 |
980–1450 ms | 160–250 ms |
SVM 4h / limit 180 |
~1190 ms | ~260 ms |
EVM 1m / limit 100 (hot pool) |
3270 ms · 1.56 GiB read · ~5.1 GB RAM | 155 ms · 262 MiB · ~314 MiB |
~7–21× faster and ~6–16× less memory per request. The memory reduction is what removes the contention behind the reported timeouts. Coarse intervals with little history (e.g. hourly/weekly presets) may take a few tens of milliseconds longer from the extra timestamp pass, but remain well within budget.
Client tip for charting: always pass
start_time/end_timefor the visible window. It further bounds the scan and lets you fetch a full preset in fewer requests.
Chores
- Bumped
dbs-config.yaml.exampleDEX dataset versions to match production (solana:svm-dex@v0.5.2,mainnet:evm-dex@v0.5.0,tron:evm-dex@v0.5.0). - Made
SKILL.mdOKF-compatible (#581).
Full changelog: v3.21.0...v3.21.1
v3.21.0
Adds the HIP-4 outcome market family on Hyperliquid, normalizes the response shape across the new /outcomes/* endpoints, and tightens a few existing surfaces.
Breaking changes
/v1/hyperliquid/markets — volume / count semantics
buy_volume_24h / sell_volume_24h now report taker-aggressor notional only (previously combined taker + maker on the matched side). volume_24h is the true matched total and trades_24h is the true match count.
| Field | Before | After |
|---|---|---|
buy_volume_24h |
bid-side notional | taker buys (aggressor on the ask) |
sell_volume_24h |
ask-side notional | taker sells (aggressor on the bid) |
volume_24h |
sum of both sides (≈ 2× true) | true matched volume |
trades_24h |
row count (≈ 2× true) | true match count |
/v1/hyperliquid/markets/ohlc, /markets/liquidations/ohlc, /platform
Same taker-derived swap as /markets, applied to the equivalent fields on each. The redundant buys / sells columns are removed from the response — after the fix both equalled the match count, so they carried no information.
/v1/hyperliquid/markets — nullable funding fields for spot rows
open_interest, funding_rate, and funding_snapshot_time now return null for spot markets (which have no funding data), instead of the sentinels 0 / 0 / 1970-01-01 00:00:00. Perp markets are unchanged.
// before
{ "coin": "@107", "dex": "spot", "open_interest": 0, "funding_rate": 0, "funding_snapshot_time": "1970-01-01 00:00:00" }
// after
{ "coin": "@107", "dex": "spot", "open_interest": null, "funding_rate": null, "funding_snapshot_time": null }New endpoints
Six new HIP-4 outcome endpoints under /v1/hyperliquid/outcomes/*:
| Endpoint | Description |
|---|---|
GET /v1/hyperliquid/outcomes |
Outcome universe with per-leg price, 24h volume, and 24h price change |
GET /v1/hyperliquid/outcomes/ohlc |
Per-leg OHLCV candles |
GET /v1/hyperliquid/outcomes/trades |
Taker fills feed (BUY/SELL + optional composition events) |
GET /v1/hyperliquid/outcomes/users |
Per-user-per-outcome P&L and volume rollup; leaderboard mode when filtered by outcome/question |
GET /v1/hyperliquid/outcomes/users/positions |
Current share holdings per (user, leg) — open balances only |
GET /v1/hyperliquid/outcomes/users/activity |
Composition-event feed (SPLIT_OUTCOME, MERGE_OUTCOME, MERGE_QUESTION, NEGATE_OUTCOME, SETTLEMENT) |
Outcome coins use the #<outcome_id*10 + side_index> encoding (e.g. #1720 = outcome 172, Yes leg; #1721 = outcome 172, No leg). Outcome coins and dex=outcome are rejected on the regular /markets/* and /users/* endpoints — use the dedicated /outcomes/* family.
Response shape on /outcomes/*
Every /outcomes/* response (except /outcomes itself, which remains the canonical full-metadata source) embeds a compact outcome context object:
OutcomeContexton/outcomes/users(aggregates collapse legs):outcome_id,outcome_name,question_id,question_name,status,settle_fraction.OutcomeLegContexton per-leg endpoints (/outcomes/ohlc,/outcomes/trades,/outcomes/users/positions,/outcomes/users/activity): the above pluscoin,side_index,side_label.
settle_fraction follows the HIP-4 spec — a value in [0, 1] representing the Yes share's payout at settlement. null until status='settled'.
Additive filters and modes (non-breaking)
?direction=…(CSV) on/outcomes/trades,/markets/activity, and/markets/liquidations, each with an endpoint-specific enum.?sort_by=…on/outcomes(volume_24h,last_trade,outcome_id) and/outcomes/users(total_volume,transactions,realized_pnl).?include_fallback=trueon/outcomesexposes each multi-outcome question's catch-all leg (off by default).?coinis a valid scope on/outcomes/users/positionsand/outcomes/users/activity, in line withoutcome_idandquestion_id.?useris optional on/outcomes/users— when omitted, the response is a leaderboard for the given?outcome_id/?question_idscope, sorted bysort_bydesc.
🤖 Generated with Claude Code
v3.21.0-pre2
Polish on top of v3.21.0-pre1
Tightens the new /outcomes/users family based on staging feedback. No infrastructure or breaking-change deltas vs. v3.21.0-pre1.
Changes
/outcomes/users/activity— direction enum now restricted to the five composition events (SETTLEMENT,SPLIT_OUTCOME,MERGE_OUTCOME,MERGE_QUESTION,NEGATE_OUTCOME). PassingBUY/SELLreturns400; taker fills remain on/outcomes/trades./outcomes/users/positions—coinis now a valid scope alongsideuser/outcome_id/question_id. Previously the param was silently ignored./outcomes/users— newsort_byparameter (total_volumedefault, alsotransactions,realized_pnl). Parity with/usersleaderboard mode.- All three endpoint descriptions now lead with the at-least-one-of constraint in bold.
Reference
- See v3.21.0-pre1 release notes for the larger Hyperliquid Outcomes feature set.
🤖 Generated with Claude Code
v3.21.0-pre1
First pre-release in the v3.21.0 cycle. Adds the HIP-4 outcome market family, unifies the response shape across /outcomes/* endpoints, and ships a few cross-family fixes.
Breaking changes
/v1/hyperliquid/markets — volume / count semantics
buy_volume_24h / sell_volume_24h now report taker-aggressor notional only (previously combined taker + maker on the matched side). volume_24h is the true matched total (was approximately 2× due to two rows per match) and trades_24h is the true match count (was approximately 2× inflated).
| Field | Before | After |
|---|---|---|
buy_volume_24h |
bid-side notional | taker buys (aggressor on the ask) |
sell_volume_24h |
ask-side notional | taker sells (aggressor on the bid) |
volume_24h |
sum of both sides (≈ 2× true) | true matched volume |
trades_24h |
row count (≈ 2× true) | true match count |
/v1/hyperliquid/markets/ohlc, /v1/hyperliquid/markets/liquidations/ohlc, /v1/hyperliquid/platform
Same taker-derived swap as /markets, applied to the equivalent fields on each. Additionally, the redundant buys / sells columns are removed from the response — after the fix both equalled the match count, so they carried no information.
/v1/hyperliquid/markets — nullable funding fields for spot rows
open_interest, funding_rate, and funding_snapshot_time now return null for spot markets (which have no funding data), instead of the sentinels 0 / 0 / 1970-01-01 00:00:00. Perp markets are unchanged.
// before
{ "coin": "@107", "dex": "spot", "open_interest": 0, "funding_rate": 0, "funding_snapshot_time": "1970-01-01 00:00:00" }
// after
{ "coin": "@107", "dex": "spot", "open_interest": null, "funding_rate": null, "funding_snapshot_time": null }New endpoints (six)
| Endpoint | Description |
|---|---|
GET /v1/hyperliquid/outcomes |
Outcome universe with per-leg price, 24h volume, and 24h price change |
GET /v1/hyperliquid/outcomes/ohlc |
Per-leg OHLCV candles |
GET /v1/hyperliquid/outcomes/trades |
Taker fills feed (BUY/SELL + optional composition events) |
GET /v1/hyperliquid/outcomes/users |
Per-user-per-outcome P&L and volume rollup; leaderboard mode when filtered by outcome/question |
GET /v1/hyperliquid/outcomes/users/positions |
Current share holdings per (user, leg) — open balances only |
GET /v1/hyperliquid/outcomes/users/activity |
Composition events feed per user (SPLIT/MERGE/MERGE_QUESTION/NEGATE/SETTLEMENT) |
Response shape on /outcomes/*
Every /outcomes/* response (except /outcomes itself, which remains the canonical full-metadata source) embeds a compact outcome context object:
OutcomeContexton/outcomes/users(aggregates collapse legs):outcome_id,outcome_name,question_id,question_name,status,settle_fraction.OutcomeLegContexton per-leg endpoints (/outcomes/ohlc,/outcomes/trades,/outcomes/users/positions,/outcomes/users/activity): the above +coin,side_index,side_label.
settle_fraction follows the HIP-4 spec — a value in [0, 1] representing the Yes share's payout at settlement. Null until status='settled'.
Additive filters (non-breaking)
?direction=...(CSV) on/v1/hyperliquid/outcomes/trades,/v1/hyperliquid/markets/activity, and/v1/hyperliquid/markets/liquidations, each with an endpoint-specific enum. Default behavior unchanged when omitted.?useris optional on/outcomes/users— when omitted, the response is a leaderboard for the given?outcome_id/?question_idscope, sorted bytotal_volumedesc.
Performance
- Responses are now gzip-encoded when
Accept-Encoding: gzipis sent. JSON payloads typically compress 5–10× on the wire. /v1/hyperliquid/outcomesis meaningfully faster — fewer source-table scans per request.
🤖 Generated with Claude Code
v3.20.6
v3.20.5
What's Changed
- fix(polymarket/ohlc): dedup market metadata join by @0237h in #557
- perf(evm): faster /holders/native (ERC-20 reverted — see proposal) by @YaroShkvorets in #558
Full Changelog: v3.20.4...v3.20.5
v3.20.4
What's Changed
- perf+fix(svm): faster pools/holders/balances + pagination & determinism correctness fixes by @YaroShkvorets in #556
Full Changelog: v3.20.3...v3.20.4
v3.20.3
What's Changed
- feat(evm/pools): return transactions count in response by @YaroShkvorets in #554
- fix(evm): exclude kyber_elastic duplicate decodes by @YaroShkvorets in #555
Full Changelog: v3.20.2...v3.20.3
v3.20.2
Performance
/v1/evm/ohlcv,/v1/evm/balances,/v1/evm/balances/historical,/v1/tvm/tokens— faster response times by lifting themetadata.metadatalookup into a CTE so the(network, contract)primary key engages, instead of scanning the full network prefix that the previous JOIN-only condition fell back to.
PRs
- #553 — perf(evm/ohlcv,balances,balances_historical,tvm/tokens): push metadata PK predicate
Full Changelog: v3.20.1...v3.20.2
v3.20.1
Fixes
/v1/evm/holders,/v1/evm/holders/native,/v1/evm/nft/collectionsnow returnnullfor fields that depend on contract-deployment data (is_contract,contract_creation,contract_creator) on chains where that data is unavailable (currentlyhyperevmandavalanche). Previously these returned misleading defaults (is_contract: falsefor every holder; epoch-zero timestamp and a null-byte creator on NFT collections).
Performance
/v1/evm/pools: faster response times via projections on the aggregating tables and PK-predicate pushdowns./v1/evm/tokens: faster response times via single-passFINALaggregation onerc20_balancesand PK-predicate pushdown on metadata.
PRs
- #550 — perf(evm/pools): use token-table projection and push PK predicates
- #551 — perf(evm/tokens): use FINAL for balances and push metadata PK predicate
- #552 — fix(evm): null-fallback for is_contract and NFT creation fields
Full Changelog: v3.20.0...v3.20.1