Repository navigation
fix(hyperliquid): submit/cancel trading-path bugs (silent error, wrong asset id, msgpack int64) - #1281
Merged
Conversation
…asset, msgpack int64→uint64
Three bugs caught by ground-truth live-trade verification:
1. submitOrder silently swallowed HL rejections. When HL returned
statuses[0].error (e.g. 'Order must have minimum value of 10 USDC'),
the SDK reported status='filled', id='unknown' — fake success. Now
raises a typed PmxtError carrying the HL message. Also handles the
filled status correctly (was checked but never populated price/oid).
2. cancelOrder hardcoded asset id 'a: 0'. HL rejected every cancel with
'User or API Wallet does not exist' because the recovered signer
address depended on the (wrong) asset id in the signed action. Now
looks up the actual order from openOrders, decodes coin → assetId,
and signs the correct cancel. Also returns a typed OrderNotFound
when the supplied oid isn't open.
3. msgpackr encoded positive BigInts as int64 (0xd3); HL's server runs
Python msgpack which encodes the same values as uint64 (0xcf). One
byte mismatch produced an action hash that recovered to a different
address — HL saw 'User or API Wallet 0xfaf6... does not exist'. Added
fixInt64ToUint64 post-processor: HL actions never carry negative
ints (oids, nonces, asset ids are all >= 0), so flipping d3→cf when
the next byte is < 0x80 is safe and matches Python's encoding.
Verified end-to-end against a live wallet (0xcb85…):
createOrder (BUY 100 @ $0.10, hl-outcome-553)
→ id=476019713300 status=open
fetch_open_orders → contains the order
cancelOrder(id) → status=canceled
fetch_open_orders → empty
cancelOrder('999999999999') → typed PmxtError 'Order not found'
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
Three real HL bugs surfaced by live ground-truth trading verification against a funded mainnet wallet:
1.
submitOrdersilently swallowed HL rejectionsWhen HL returned
statuses[0].error(e.g."Order must have minimum value of 10 USDC"), the SDK reportedstatus='filled', id='unknown'— fake success. The order didn't exist, but the caller had no way to know.→ Now raises a typed
PmxtErrorcarrying HL's message. Also handles thefilledbranch correctly (was checked but never populatedpriceoroidin the response).2.
cancelOrderhardcodeda: 0(asset id)Every cancel signed an action with
cancels: [{a: 0, o: <oid>}]. HL rejected withUser or API Wallet 0xfaf6… does not existbecause the action hash with the wrong asset recovers a different signer address.→ Now looks up the open order to derive the real asset id via
encodeAssetId. Throws typedOrder not foundwhen the supplied oid isn't open.3. msgpack int64 vs uint64 — one byte off
msgpackrencodes positive BigInts as int64 (0xd3); HL's server (Pythonmsgpack) encodes the same values as uint64 (0xcf). Identical bit pattern, different type byte → action hash mismatch → signature recovers to wrong address. Only manifested on cancel because order actions don't carry BigInt fields; cancel does (oid).→ Added
fixInt64ToUint64post-processor. HL actions never carry negative ints (oids, nonces, asset ids are all ≥ 0), so flippingd3 → cfwhen the following byte is< 0x80is safe and produces byte-identical encoding to Python msgpack.Verified end-to-end against live wallet
0xcb85…No funds were lost in verification (orders rested far below market and were cancelled within seconds).
Test plan