feat: Implement Aevo Perpetual Connector#1
feat: Implement Aevo Perpetual Connector#1SBALAVIGNESH123 wants to merge 23 commits intodevelopmentfrom
Conversation
sync / Client staging -> master for Hummingbot version 2.10.0
sync / Client development -> staging v2.11
sync / add modify side to avoid errors to staging
sync / staging to main v2.11
There was a problem hiding this comment.
This PR is being reviewed by Cursor Bugbot
Details
You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
| f"{CONSTANTS.WS_TOPIC_TRADES}:{pair}" | ||
| ] | ||
| } | ||
| await ws.send_json(subscribe_request) |
There was a problem hiding this comment.
WebSocket subscriptions missing symbol format conversion
The WebSocket subscription uses pair from self._trading_pairs directly without converting to exchange format (e.g., subscribing with "ETH-USD" instead of "ETH-PERP"). REST endpoints like get_new_order_book correctly call utils.convert_to_exchange_symbol() before making requests. Additionally, when parsing WebSocket responses, channel.split(":")[-1] extracts the trading pair in exchange format but never converts it back to HB format using utils.convert_to_hb_symbol(). This inconsistency causes trading pair mismatches between WebSocket data and the rest of the system.
Additional Locations (2)
| "asks": snapshot.get("asks", []) | ||
| }, | ||
| timestamp=timestamp * 1e-9 | ||
| ) |
There was a problem hiding this comment.
Method returns OrderBookMessage but declares OrderBook return type
The get_new_order_book method signature declares a return type of OrderBook but the implementation returns an OrderBookMessage instance at line 60. Callers expecting an OrderBook object will receive an incompatible OrderBookMessage type, causing method calls and attribute access to fail at runtime. Other connectors in the codebase that implement get_new_order_book correctly return OrderBook objects.
| # Check base class: OrderBookTrackerDataSource usually returns OrderBookMessage from snapshot. | ||
| from hummingbot.core.data_type.order_book_message import OrderBookMessage, OrderBookMessageType | ||
|
|
||
| timestamp = snapshot.get("timestamp", self._time_synchronizer.time() * 1e9) |
There was a problem hiding this comment.
Optional time_synchronizer accessed without null check
The _time_synchronizer parameter is declared as Optional[Any] = None in __init__, but the code accesses self._time_synchronizer.time() at multiple locations without null checks. When the API response lacks a timestamp and _time_synchronizer is None, this causes an AttributeError crash. The fallback mechanism using .get(..., self._time_synchronizer.time() * 1e9) evaluates the default value before checking if the key exists, so the None access occurs even when a timestamp is present.
Additional Locations (2)
| }, | ||
| timestamp=payload.get("timestamp", self._time_synchronizer.time() * 1e9) * 1e-9 | ||
| ) | ||
| self._message_queue.put_nowait(order_book_message) |
There was a problem hiding this comment.
Calling put_nowait on dict instead of Queue
The code calls self._message_queue.put_nowait() directly, but _message_queue inherited from OrderBookTrackerDataSource is a Dict[str, asyncio.Queue], not a Queue. Other connectors correctly use self._message_queue[self._snapshot_messages_queue_key].put_nowait() or similar keyed access. This will raise an AttributeError at runtime.
Additional Locations (1)
| # Verify Auth was called | ||
| self.mock_auth.get_ws_auth_payload.assert_called_once() | ||
| # Verify Auth message sent | ||
| print(f"DEBUG calls: {self.mock_ws_connection.send_json.call_args_list}") |
fix/commlib-bug
|
|
||
| async def start_network(self): | ||
| await self._stop_network() | ||
| self._stop_network_task = asyncio.create_task(self._start_network()) |
There was a problem hiding this comment.
Network task not cancelled during stop causes resource leak
The start_network method creates a task stored in _stop_network_task, but the _stop_network method only cancels _status_polling_task and never cancels _stop_network_task. When start_network is called multiple times (which calls _stop_network first), the previous _start_network task becomes orphaned and continues running. This causes resource leaks and potentially duplicate trackers/polling loops running concurrently. The variable naming also appears wrong - it stores a start task in a stop-named variable.
Additional Locations (1)
| exchange_order_id = str(response.get("order_id", order_id)) | ||
| transact_time = float(response.get("timestamp", self._time_synchronizer.time() * 1e9)) * 1e-9 | ||
|
|
||
| return exchange_order_id, transact_time |
There was a problem hiding this comment.
Order type parameter ignored in place order method
The _place_order method accepts an order_type parameter but completely ignores it. The connector claims to support both OrderType.LIMIT and OrderType.MARKET in supported_order_types, but the implementation always sends limit_price in the request params regardless of order type. Other perpetual connectors (like Binance, Bitmart) correctly use order_type to set the type field and conditionally include price only for limit orders. Market orders placed through this connector would either fail or be incorrectly submitted as limit orders.
Description
Implemented the Aevo Perpetual Connector for Hummingbot.
Changes
Verification
All unit tests passed. See walkthrough for details.
Note
Introduces a new Aevo Perpetual derivative connector with REST/WS market data, private streams, auth, and basic trading ops.
aevo_perpetual_derivative,aevo_perpetual_api_order_book_data_source,aevo_perpetual_user_stream_data_source,aevo_perpetual_auth,aevo_perpetual_constants,aevo_perpetual_utilsaevo_perpetual_constantsPOST /orders) and cancel (DELETE /orders/{id}); symbol mappingETH-USD↔ETH-PERPconf_fee_overrides_TEMPLATE.yml; pinscommlib-py==0.11.5in env filesWritten by Cursor Bugbot for commit 332e02f. This will update automatically on new commits. Configure here.