Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ COPY LICENSE .
COPY README.md .
COPY DATA_COLLECTION.md .

# ARG CONNECTOR_FILE_NAME
# ARG CONNECTOR_DEST_FILE_NAME
# COPY setup_connector.sh /home/hummingbot/
# RUN chmod +x /home/hummingbot/setup_connector.sh && /home/hummingbot/setup_connector.sh

# activate hummingbot env when entering the CT
SHELL [ "/bin/bash", "-lc" ]
RUN echo "conda activate hummingbot" >> ~/.bashrc
Expand Down
2 changes: 2 additions & 0 deletions hummingbot/connector/connector_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
'hitbtc': 'bronze',
'hyperliquid_perpetual_testnet': 'bronze',
'hyperliquid_perpetual': 'bronze',
'hook_odyssey_perpetual': 'bronze',
'hook_odyssey_perpetual_testnet': 'bronze',
'huobi': 'silver',
'kraken': 'bronze',
'kucoin': 'silver',
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cdef class dummy():
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cdef class dummy():
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import asyncio
from typing import TYPE_CHECKING, Any, Dict, List, Optional

from hummingbot.connector.derivative.hook_odyssey_perpetual.hook_odyssey_perpetual_data_source import (
HookOdysseyPerpetualDataSource,
)
from hummingbot.core.data_type.funding_info import FundingInfo
from hummingbot.core.data_type.order_book_message import OrderBookMessage, OrderBookMessageType
from hummingbot.core.data_type.perpetual_api_order_book_data_source import PerpetualAPIOrderBookDataSource
from hummingbot.core.event.event_forwarder import EventForwarder
from hummingbot.core.event.events import OrderBookEvent
from hummingbot.core.web_assistant.ws_assistant import WSAssistant
from hummingbot.logger import HummingbotLogger

if TYPE_CHECKING:
from hummingbot.connector.derivative.hook_odyssey_perpetual.hook_odyssey_perpetual_derivative import (
HookOdysseyPerpetualDerivative,
)


class HookOdysseyPerpetualAPIOrderBookDataSource(PerpetualAPIOrderBookDataSource):
_hpopobds_logger: Optional[HummingbotLogger] = None

def __init__(
self,
trading_pairs: List[str],
connector: "HookOdysseyPerpetualDerivative",
data_source: HookOdysseyPerpetualDataSource,
domain: str,
):
super().__init__(trading_pairs)
self._connector = connector
self._domain = domain
self._data_source = data_source
self._forwarders = []
self._configure_event_forwarders()

async def get_last_traded_prices(self, trading_pairs: List[str], domain: Optional[str] = None) -> Dict[str, float]:
return await self._connector.get_last_traded_prices(trading_pairs=trading_pairs)

async def listen_for_subscriptions(self):
# The socket reconnection is managed by the data_source. This method should do nothing
pass

async def _parse_order_book_snapshot_message(self, raw_message: OrderBookMessage, message_queue: asyncio.Queue):
# In HookOdysseyPerpetual, 'raw_message' is the OrderBookMessage from the data source
message_queue.put_nowait(raw_message)

async def _connected_websocket_assistant(self) -> WSAssistant:
# HookOdysseyPerpetual uses GraphQL websockets to consume stream events
raise NotImplementedError

async def _subscribe_channels(self, ws: WSAssistant):
# HookOdysseyPerpetual uses GraphQL websockets to consume stream events
raise NotImplementedError

async def _order_book_snapshot(self, trading_pair: str) -> OrderBookMessage:
return await self._data_source.get_order_book_snapshot(trading_pair)

async def _parse_trade_message(self, raw_message: OrderBookMessage, message_queue: asyncio.Queue):
# In HookOdysseyPerpetual, 'raw_message' is the OrderBookMessage from the data source
message_queue.put_nowait(raw_message)

async def _parse_order_book_diff_message(self, raw_message: OrderBookMessage, message_queue: asyncio.Queue):
# In HookOdysseyPerpetual, 'raw_message' is the OrderBookMessage from the data source
message_queue.put_nowait(raw_message)

async def get_funding_info(self, trading_pair: str) -> FundingInfo:
funding_info = await self._data_source.get_funding_info(trading_pair)
return funding_info

async def _parse_funding_info_message(self, raw_message: Dict[str, Any], message_queue: asyncio.Queue):
"""
Placeholder method for parsing funding info messages. Actual implementation needed.
"""
pass

def _configure_event_forwarders(self):
# Forward order book diffs
order_book_event_forwarder = EventForwarder(to_function=self._process_order_book_event)
self._forwarders.append(order_book_event_forwarder)
self._data_source.add_listener(
event_tag=OrderBookEvent.OrderBookDataSourceUpdateEvent,
listener=order_book_event_forwarder,
)

# Forward trade updates
trade_event_forwarder = EventForwarder(to_function=self._process_public_trade_event)
self._forwarders.append(trade_event_forwarder)
self._data_source.add_listener(event_tag=OrderBookEvent.TradeEvent, listener=trade_event_forwarder)

def _process_order_book_event(self, order_book_diff: OrderBookMessage):
if order_book_diff.type == OrderBookMessageType.SNAPSHOT:
self._message_queue[self._snapshot_messages_queue_key].put_nowait(order_book_diff)
else:
self._message_queue[self._diff_messages_queue_key].put_nowait(order_book_diff)

def _process_public_trade_event(self, trade_update: OrderBookMessage):
self._message_queue[self._trade_messages_queue_key].put_nowait(trade_update)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from hummingbot.core.data_type.in_flight_order import OrderState

EXCHANGE_NAME = "hook_odyssey_perpetual"
DOMAIN = EXCHANGE_NAME
TESTNET_DOMAIN = "hook_odyssey_perpetual_testnet"
SUPPORTED_COLLATERAL = ["ETH", "USDC"]

BASE_URLS = {
DOMAIN: "https://api-prod.hook.xyz/query",
TESTNET_DOMAIN: "https://goerli-api.hook.xyz/query",
}

WS_URLS = {
DOMAIN: "wss://api-prod.hook.xyz/query",
TESTNET_DOMAIN: "wss://goerli-api.hook.xyz/query",
}

# Order Statuses
# Note: "Partially Matched" and "Matched" are ignored because they are not final states
ORDER_STATE = {
"OPEN": OrderState.OPEN,
"PARTIALLY_FILLED": OrderState.PARTIALLY_FILLED,
"FILLED": OrderState.FILLED,
"CANCELED": OrderState.CANCELED,
"EXPIRED": OrderState.CANCELED,
"REJECTED": OrderState.FAILED,
"UNFILLABLE": OrderState.FAILED,
"FAILED": OrderState.FAILED,
}

RATE_LIMITS = []

# EIP 712
EIP712_DOMAIN_NAME = "Hook"
EIP712_DOMAIN_VERSION = "1.0.0"

CONTRACT_ADDRESSES = {
DOMAIN: "0xF9Bd1BaB25442A3b6888f2086736C6aC76A4Cf4B",
TESTNET_DOMAIN: "0x64247BeF0C0990aF63FCbdd21dc07aC2b251f500",
}

CHAIN_IDS = {
DOMAIN: 4665,
TESTNET_DOMAIN: 46658378,
}

DEFAULT_TIMEOUT = 3
Loading