Repository navigation
feat(sdk): add an opt-in order batcher with bounded queues and per-order results - #170
Merged
Merged
Conversation
…der results createOrderBatcher (actions/orderBatcher) collects independent single-order callers into shared order actions: one signature, one nonce, and one request per batch, with each caller settling exactly once with its own status. - Size, time, and explicit flush thresholds; bounded queue with immediate rejection when full; queued and post-dispatch cancellation; expiry; close with or without drain. Never retries an ambiguous batch. - Partitions by grouping, builder, vault, expiresAfter, and order class (ALO apart from IOC/GTC; split by tif and reduce-only under priority grouping). - Mixed responses keep successful items; whole-batch rejection, cardinality mismatch, and transport failure reject every caller in the batch. - Orders are validated per caller at enqueue and the batch is executed through the shared executeAction core without validating each order again. - Tests on FakeRuntime, including wire parity with order(), immediate dispatch of ExchangeClient.order next to a batcher, and HTTP weight charged once per batch. Benchmark in .dev/perf/order_batching.ts; docs in clients.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TP/SL groupings link the orders of one action, so batching independent
callers under them could attach one caller's stop-loss to another
caller's entry order. enqueue now accepts only "na" and { p }.
Co-Authored-By: Claude Opus 5.5 <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
createOrderBatcher(@bloxwap/hyperliquid/actions/orderBatcher, also re-exported fromactions): an opt-in helper that collects independent single-order callers into sharedorderactions, signs and posts once per batch, and settles each caller with its own status. Existing order APIs are untouched.enqueue(order, options),flush(),close({ drain }),pending. ConfigurablemaxQueueSize(queued + in-flight, default 1000),maxBatchSize(default 100),flushIntervalMs(default 1), and an injectableruntime(Inject transport runtime dependencies for isolated, deterministic tests #158).{ p }), where the exchange requires all-IOC or all non-reduce-only ALO, orders are also split by tif and reduce-only, so one caller's order cannot invalidate another's batch. Signer/network is fixed per batcher (bound to one config); the only action type isorder.ApiRequestErrorfrom mixed statuses is unwrapped from its retainedresponse, every status is shape-checked, and each caller gets its own status (resting/filled/waitingFor*/{ error }). A top-level rejection, cardinality mismatch, or transport failure rejects every caller in that batch.expiresAfterrejects before sending.close()drains;close({ drain: false })rejects waiters without implying server cancellation. Ambiguous batches are never retried.canonicalActionfrom those validated parts and run throughexecuteAction, so it uses the same nonce, dispatch-policy (Add an explicit bounded dispatch policy for out-of-order signing completion #160), and transport paths asexchange.execute, and orders are not validated a second time. A test checks wire parity withbuildOrderfor the same orders.Acceptance criteria
flush batches compatible callers...test (1 request, 1 signature), plus a partitioning test covering builder, vault, expiresAfter, grouping, ALO vs GTC/IOC, and the priority-grouping class split._settleis guarded; statuses map by index;_batcherCounts.test.tschecks that cancelled/flushed generations do not skew thresholds.FakeRuntime, withpendingTimers == 0checks.HttpTransportwithrateLimitand shows an 80-order batch charges exactly 3 weight (1 + floor(80/40)), not 80.ExchangeClient.ordernext to a batcher with queued orders: it dispatches immediately, and still rejects mixed responses withApiRequestError, while the batcher returns per-order outcomes..dev/perf/order_batching.ts(results below).clients.md, along with cancellation semantics, close/drain, no retry, REST weight1 + floor(n/40)vs. address-based limits, and ALO separation.Measurements
bun .dev/perf/order_batching.ts: 300 single-order callers, real secp256k1 signing (viem account), 5 ms mock transport, median of 5 alternating rounds. Bun 1.4.0-canary.1, Apple M3 Max. These are wall-clock timings with mocks, not production latency. "direct" means oneorder()call per caller.peakQueueisbatcher.pending(queued plus in-flight), or outstanding calls for direct.How to read it:
Notes:
tests/perf: the measurements live in.dev/perf/order_batching.ts, not in thetests/perftransaction suite the issue links. The Performance workflow fingerprints the wholetests/perfsource tree and fails closed when it differs between base and head, so adding a scenario there would fail the gate for this PR. The.dev/perfscript follows the existingremote_signing.tspattern.hill_climb.tsqueue block and the combinedapi_design.tsharness are not on main and are not needed by this issue.Test plan
bun run check(format, lint, docs, types, ts7, jsdoc, exports, import budgets)bun run test:offline: 2071 pass, 0 failbun run build, including the published-consumer type check forcreateOrderBatcher/OrderOutcomebun .dev/perf/order_batching.tsCloses #159
🤖 Generated with Claude Code