Skip to content

Webhooks, CVD, HIP-3 oracle, HIP-4 questions, wallet classification, symbols - #19

Merged
0xFantomMenace merged 2 commits into
masterfrom
feat/surface-parity
Sep 29, 2026
Merged

0xFantomMenace merged 2 commits into
masterfrom
feat/surface-parity

Conversation

@0xFantomMenace

Copy link
Copy Markdown
Member

Brings the SDK to parity with the customer-facing API for 1.12.0. Everything is added under the existing ## 1.12.0 (2026-09-28) CHANGELOG section; the version is unchanged.

Added

Webhooks (client.webhooks, all 21 /v1/webhooks routes)

Method Route
eventTypes() GET /v1/webhooks/event-types
limits() GET /v1/webhooks/limits
listEndpoints() GET /v1/webhooks/endpoints
createEndpoint(params) POST /v1/webhooks/endpoints
deleteEndpoint(id) DELETE /v1/webhooks/endpoints/{id}
enableEndpoint(id) POST /v1/webhooks/endpoints/{id}/enable
rotateSecret(id) POST /v1/webhooks/endpoints/{id}/rotate
testEndpoint(id) POST /v1/webhooks/endpoints/{id}/test
listDeliveries(id, params?) GET /v1/webhooks/endpoints/{id}/deliveries
redeliver(id) POST /v1/webhooks/deliveries/{id}/redeliver
listSubscriptions() GET /v1/webhooks/subscriptions
createSubscription(params) POST /v1/webhooks/subscriptions
updateSubscription(id, params) PATCH /v1/webhooks/subscriptions/{id}
deleteSubscription(id) DELETE /v1/webhooks/subscriptions/{id}
resumeSubscription(id) POST /v1/webhooks/subscriptions/{id}/resume
resumeAllSubscriptions() POST /v1/webhooks/subscriptions/resume
dryRun(params) POST /v1/webhooks/subscriptions/dry-run
estimate(params) POST /v1/webhooks/subscriptions/estimate
listAddresses() GET /v1/webhooks/addresses
addAddress(params) POST /v1/webhooks/addresses
deleteAddress(id) DELETE /v1/webhooks/addresses/{id}

This ports the resource from feat/webhooks-resource (#9) onto current master and reconciles it with the spec: limits(), both resume routes and the subscription pause fields are new, and the redelivery result, cost floor and estimate basis follow the spec shapes.

Signature verification: constructWebhookEvent(), verifyWebhookSignature() and assertWebhookSignature(), plus createWebhookSignatureHeader(), parseWebhookSignatureHeader() and readWebhookHeader(). They take the raw body (string, Buffer, Uint8Array, ArrayBuffer) and refuse a parsed object, accept any v1 in 0xa-signature against any secret passed (both signatures during a rotation), compare in constant time, and enforce a 300 second replay window in both directions. A NaN tolerance or clock throws instead of switching the check off. The README publishes fixed test vectors, which the tests check against an independent HMAC.

Market data

Method Route
hyperliquid.cvd.history(symbol, params?) GET /v1/hyperliquid/cvd/{symbol}
hyperliquid.hip3.cvd.history(symbol, params?) GET /v1/hyperliquid/hip3/cvd/{symbol}
hyperliquid.hip3.oracle.discoveryBounds(symbol) GET /v1/hyperliquid/hip3/oracle/discovery-bounds/{symbol}
hyperliquid.hip3.oracle.externalPrice(symbol) GET /v1/hyperliquid/hip3/oracle/external-price/{symbol}
hyperliquid.hip4.questions.list(params?) (and hip4.listQuestions()) GET /v1/hyperliquid/hip4/questions
hyperliquid.hip4.questions.get(id) (and hip4.getQuestion()) GET /v1/hyperliquid/hip4/questions/{question_id}
hyperliquid.wallets.classify(params?) GET /v1/hyperliquid/wallets/classify
hyperliquid.hip3.wallets.classify(params?) GET /v1/hyperliquid/hip3/wallets/classify
symbols.list() GET /v1/symbols

CVD and questions return nextCursor, passed back unchanged. Types and Zod schemas cover every new response.

WebSocket: orderbook_full and hip3_orderbook_full join WsChannel and WsChannelSchema, with WsL2FullDepthSnapshot / WsL2FullDepthBatch types for the l4_snapshot + l4_batch messages these channels send. The API answers a replay of either channel with "does not support historical replay", so replay() and multiReplay() refuse them before sending, the same way the live-only L4 channels are handled.

Changed / fixed

  • HTTP layer: PATCH and DELETE, one shared request path for every verb, and the option to keep free-form subtrees (webhook filters, payload, occurrence data, catalog maps, symbol coverage maps) exactly as sent.
  • OxArchiveError.requestId is now set on errors; the error envelope carries request_id at the top level, not under meta.
  • hip4.outcomes.list({ isSettled }) sent isSettled, which the API ignores, so the filter never applied. It now sends is_settled.
  • Order flow: folds in the README and JSDoc from HELD until the API returns next_cursor on order flow: document order-flow paging #14, which follow nextCursor with the same window. orders.flow() on core, HIP-3 and HIP-4 already forwards cursor; tests cover all three.

Checks

  • npm run build, npx tsc --noEmit -p .: clean
  • npx vitest run: 248 passed (96 new: 31 webhooks resource, 37 signature verifier, 28 market data and WebSocket)
  • Package contents check: the tarball holds dist, README.md, LICENSE, package.json only
  • The new read routes, and the webhook list/limits/catalog reads, were run against the live API with validate: true. Webhook write routes are covered by mocked tests only.

…symbols

Brings the SDK to parity with the customer-facing API for 1.12.0.

Webhooks: client.webhooks covers all 21 /v1/webhooks routes: the event
catalog and plan limits, endpoints (list, create, delete, enable, rotate
secret, test), the delivery log and repeat delivery, subscriptions (list,
create, update, delete, resume one, resume all), the estimate and dry-run
previews, and watched addresses. It is ported from the earlier
feat/webhooks-resource work and reconciled with the current spec: limits,
the two resume routes and the subscription pause fields are new, and the
redelivery, cost floor and estimate basis shapes follow the spec.

The signature verifier takes the raw body (string, Buffer, Uint8Array or
ArrayBuffer) and refuses a parsed object, accepts any v1 in 0xa-signature
against any secret passed so a rotation verifies with either secret,
compares in constant time, and enforces a 300 second replay window. A NaN
tolerance or clock is refused rather than silently disabling the check.

The HTTP layer gains PATCH and DELETE on one shared request path, can keep
free-form subtrees (webhook filters, payloads, catalog maps, symbol
coverage maps) exactly as sent, and now reads the request id that error
responses carry at the top level.

Also added: CVD for Hyperliquid core and HIP-3 (cursor paged), HIP-3
oracle external price and discovery bounds, HIP-4 questions, wallet
classification for core and HIP-3, and client.symbols.list(). The
orderbook_full and hip3_orderbook_full WebSocket channels are typed for
live use; the API does not replay them, so replay requests for them are
refused before sending.

Fixes hip4.outcomes.list() sending isSettled, which the API ignores; it
now sends is_settled.

Folds in the order-flow paging docs from docs/order-flow-paging.
@0xFantomMenace
0xFantomMenace merged commit cc40323 into master Sep 29, 2026
1 check passed
@0xFantomMenace
0xFantomMenace deleted the feat/surface-parity branch September 29, 2026 03:13
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.

1 participant