Skip to content

fix(python): resolve HTTP client and trade message bugs#2

Open
manassehnnad1 wants to merge 1 commit into
Bulk-trade:mainfrom
manassehnnad1:fix/python-http-client-bugs
Open

fix(python): resolve HTTP client and trade message bugs#2
manassehnnad1 wants to merge 1 commit into
Bulk-trade:mainfrom
manassehnnad1:fix/python-http-client-bugs

Conversation

@manassehnnad1

Copy link
Copy Markdown

Summary

this PR fixes four bugs in the Python HTTP client that collectively prevent
any order from being placed successfully using the SDK as shipped.

Bug 1 — public_key called as a function (http_client.py)

image

TransactionSigner.public_key is a plain string attribute, not a callable.
Calling it with () raises TypeError: 'str' object is not callable
immediately, making place_orders() completely unusable.

# before
account = self.signer.public_key()

# after
account = self.signer.public_key

Bug 2 — Nonce sent as string with wrong source (http_client.py)

image

Two problems on the same line:

  1. The nonce is wrapped in an f-string, sending it as "1778724349688225000"
    instead of the integer 1778724349688225000.
  2. order_objects[0].nonce references .nonce on a plain dict returned by
    tx.to_api(). Dicts have no .nonce attribute, raising
    AttributeError: 'dict' object has no attribute 'nonce'.

The nonce variable is already correctly defined earlier in the function
and should be used directly.

# before
"nonce": f"{order_objects[0].nonce}",

# after
"nonce": nonce,

Bug 3 — px and sz sent as strings in LimitOrder.to_api() (trade.py)

image

Price and size are wrapped in f-strings, sending them as JSON strings
("79.6") instead of JSON numbers (79.6). The API requires numeric
values and rejects string values with a 422 error.

The same issue affects sz in MarketOrder, Stop, TakeProfit, and
TrailingStop and has been fixed in all locations.

# before
'px': f"{self.price}",
'sz': f"{self.size}",

# after
'px': float(self.price),
'sz': float(self.size),

Bug 4 — Wrong response parsing path in OrderResponse.from_api() (trade.py)

The method navigates data.payload.response.data.statuses which does not
exist in the actual API response. The real structure is
response.data.statuses. This causes from_api() to always return an
empty list [] regardless of the actual server response, making it
impossible to know if an order succeeded, failed, or what its order ID is.

# before
rlist = data.get("data",{}).get("payload",{}).get("response",{}).get("data",{}).get("statuses", [])

# after
rlist = data.get("response",{}).get("data",{}).get("statuses", [])

Impact

Bugs 1–3 together mean no order can ever be placed using the Python SDK
as shipped. Bug 4 means even if an order did go through, the caller would
never know
because responses always parse as empty.

These bugs were discovered while building a Claude-powered autonomous
trading agent on BULK testnet using the Python SDK.

Testing

All fixes have been verified against the staging environment
(staging-api.bulk.trade). Orders now place successfully and responses
parse correctly, returning the expected resting status and order IDs.

image image

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