def test_get_candlesticks_structure(self): """ Check if response match expected dict structure. :return: """ expect: dict = { 'id': str, 'sequence_number': int, 'result': [{ 'id': int, 'market': str, 'time': str, 'resolution': int, 'open': str, 'close': str, 'high': str, 'low': str, 'volume': str, 'quote_volume': str }] } # connect to websocket client = DemexWebsocket(uri=MAINNET_WS_URI) # little work around to save the response self.response: List[Optional[dict]] = [] async def on_connect(): for granularity in [1, 5, 15, 30, 60, 360, 1440]: from_epoch = int(time.time() - granularity * 1000) to_epoch = int(time.time()) await client.get_candlesticks('candlesticks', "eth1_usdc1", granularity, from_epoch, to_epoch) async def on_message(message: dict): # save response into self self.response.append(message) try: loop = asyncio.get_event_loop() loop.run_until_complete( asyncio.wait_for( client.connect(on_connect_callback=on_connect, on_receive_message_callback=on_message), WEBSOCKET_TIMEOUT_GET_REQUEST)) except asyncio.TimeoutError: loop = asyncio.get_event_loop() loop.run_until_complete(client.disconnect()) if not self.response: raise RuntimeError("Did not receive a response.") for response in self.response: if response["result"]: self.assertDictStructure(expect, response)
def test_get_account_trades_structure(self): """ Check if response match expected dict structure. :return: """ expect: dict = { "id": str, "result": [{ "base_precision": int, "quote_precision": int, "fee_precision": int, "order_id": str, "market": str, "side": str, "quantity": str, "price": str, "fee_amount": str, "fee_denom": str, "address": str, "block_height": str, "block_created_at": str, "id": int }] } # connect to websocket client = DemexWebsocket(uri=MAINNET_WS_URI) # little work around to save the response self.response: Optional[dict] = None async def on_connect(): await client.get_account_trades('account_trades', WALLET_DEVEL) async def on_message(message: dict): # save response into self self.response = message await client.disconnect() try: loop = asyncio.get_event_loop() loop.run_until_complete( asyncio.wait_for( client.connect(on_connect_callback=on_connect, on_receive_message_callback=on_message), WEBSOCKET_TIMEOUT_GET_REQUEST)) except concurrent.futures._base.TimeoutError: raise TimeoutError("Test did not complete in time.") if not self.response: raise RuntimeError("Did not receive a response.") self.assertDictStructure(expect, self.response) self.assertTrue( len(self.response["result"]) == 100, msg= f"Expected 100 recent trades, got {len(self.response['result'])}")
def test_get_recent_trades_structure(self): """ Check if response match expected dict structure. :return: """ expect: dict = { "id": str, "sequence_number": int, "result": [ { "id": str, "block_created_at": str, "taker_id": str, "taker_address": str, "taker_fee_amount": str, "taker_fee_denom": str, "taker_side": str, "maker_id": str, "maker_address": str, "maker_fee_amount": str, "maker_fee_denom": str, "maker_side": str, "market": str, "price": str, "quantity": str, "liquidation": str, "taker_username": str, "maker_username": str, "block_height": str }, ] } # connect to websocket client = DemexWebsocket(uri=MAINNET_WS_URI) # little work around to save the response self.response: Optional[dict] = None async def on_connect(): await client.get_recent_trades("recent_trades", "swth_eth1") async def on_message(message: dict): # save response into self self.response = message await client.disconnect() try: loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait_for(client.connect(on_connect_callback=on_connect, on_receive_message_callback=on_message), WEBSOCKET_TIMEOUT_GET_REQUEST)) except asyncio.TimeoutError: raise TimeoutError("Test did not complete in time.") if not self.response: raise RuntimeError("Did not receive a response.") self.assertDictStructure(expect, self.response)
def test_subscribe_books_structure(self): """ Check if response match expected dict structure. :return: """ expect_subscription: dict = {'id': str, 'result': [str]} expect: dict = { 'channel': str, 'sequence_number': int, 'result': [{ 'market': str, 'price': str, 'quantity': str, 'side': str, 'type': str }] } # connect to websocket client = DemexWebsocket(uri=MAINNET_WS_URI) # little work around to save the response self.response: List[dict] = [] async def on_connect(): await client.subscribe_books('book', "eth1_usdc1") async def on_message(message: dict): # save response into self self.response.append(message) try: loop = asyncio.get_event_loop() loop.run_until_complete( asyncio.wait_for( client.connect(on_connect_callback=on_connect, on_receive_message_callback=on_message), WEBSOCKET_TIMEOUT_SUBSCRIPTION)) except asyncio.TimeoutError: loop = asyncio.get_event_loop() loop.run_until_complete(client.disconnect()) if not self.response: raise RuntimeError("Did not receive a response.") self.assertTrue( len(self.response) >= 2, msg= f"Expected at least 2 messages: channel subscription and an update message" ) channel_subscription: dict = self.response[0] self.assertDictStructure(expect_subscription, channel_subscription) for message in self.response[1:]: self.assertDictStructure(expect, message)
def test_get_candlesticks_wrong_granularity(self): """ Check if the method catches wrong granularities. :return: """ # connect to websocket client = DemexWebsocket(uri="") for wrong_granularity in [0, 2, 4, 6, 100, 1500]: with self.assertRaises(ValueError): loop = asyncio.get_event_loop() loop.run_until_complete( client.get_candlesticks("candle", "swth_eth1", wrong_granularity, 0, 0))
def test_unsubscribe_structure(self): """ Check if response match expected dict structure. :return: """ expect_subscription: dict = {'id': str, 'result': [str]} # connect to websocket client = DemexWebsocket(uri=MAINNET_WS_URI) # little work around to save the response self.response: List[dict] = [] async def on_connect(): # use AMM to be sure deterministic of which tokens the wallet holds await client.subscribe_balances('balance', WALLET_SWTH_ETH1_AMM) async def on_message(message: dict): # save response into self if "id" in message.keys(): self.response.append(message) if len(self.response) == 1: await client.unsubscribe("unsubscribe", self.response[0]["result"]) try: loop = asyncio.get_event_loop() loop.run_until_complete( asyncio.wait_for( client.connect(on_connect_callback=on_connect, on_receive_message_callback=on_message), WEBSOCKET_TIMEOUT_GET_REQUEST)) except asyncio.TimeoutError: loop = asyncio.get_event_loop() loop.run_until_complete(client.disconnect()) if not self.response: raise RuntimeError("Did not receive a response.") self.assertTrue( len(self.response) >= 2, msg= f"Expected at least 2 messages: channel subscription and and first update message" ) channel_subscription: dict = self.response[0] self.assertDictStructure(expect_subscription, channel_subscription) channel_unsubscription: dict = self.response[1] self.assertDictStructure(expect_subscription, channel_unsubscription)
def test_subscribe_recent_trades_structure(self): """ Check if response match expected dict structure. :return: """ expect_subscription: dict = {'id': str, 'result': [str]} expect: dict = { 'channel': str, 'sequence_number': int, 'result': [{ 'id': str, 'block_created_at': str, 'taker_id': str, 'taker_address': str, 'taker_fee_amount': str, 'taker_fee_denom': str, 'taker_side': str, 'maker_id': str, 'maker_address': str, 'maker_fee_amount': str, 'maker_fee_denom': str, 'maker_side': str, 'market': str, 'price': str, 'quantity': str, 'liquidation': str, 'taker_username': str, 'maker_username': str, 'block_height': str, }] } # connect to websocket client = DemexWebsocket(uri=MAINNET_WS_URI) # little work around to save the response self.response: List[dict] = [] async def on_connect(): # use AMM to be sure deterministic of which tokens the wallet holds await client.subscribe_recent_trades('orders', "eth1_usdc1") async def on_message(message: dict): # save response into self self.response.append(message) try: loop = asyncio.get_event_loop() loop.run_until_complete( asyncio.wait_for( client.connect(on_connect_callback=on_connect, on_receive_message_callback=on_message), WEBSOCKET_TIMEOUT_SUBSCRIPTION)) except asyncio.TimeoutError: loop = asyncio.get_event_loop() loop.run_until_complete(client.disconnect()) if not self.response: raise RuntimeError("Did not receive a response.") if len(self.response) < 2: self.skipTest( f"Did not receive orders within time, test can not finish.") channel_subscription: dict = self.response[0] self.assertDictStructure(expect_subscription, channel_subscription) for message in self.response[1:]: # if this fails, check if the AMM wallet own other tokens as expected self.assertDictStructure(expect, message)
def test_get_market_stats_structure(self): """ Check if response match expected dict structure. :return: """ market_stats: dict = { "day_high": str, "day_low": str, "day_open": str, "day_close": str, "day_volume": str, "day_quote_volume": str, "index_price": str, "mark_price": str, "last_price": str, "market": str, "market_type": str, "open_interest": str } expect: dict = { 'id': str, 'result': { 'cel1_usdc1': market_stats, 'eth1_usdc1': market_stats, 'eth1_wbtc1': market_stats, 'nex1_usdc1': market_stats, 'nneo2_usdc1': market_stats, 'swth_eth1': market_stats, 'swth_usdc1': market_stats, 'wbtc1_usdc1': market_stats, 'btc_h21': market_stats, 'eth_h21': market_stats, } } # connect to websocket client = DemexWebsocket(uri=MAINNET_WS_URI) # little work around to save the response self.response: Optional[dict] = None async def on_connect(): await client.get_market_stats("market_stats") async def on_message(message: dict): # save response into self self.response = message await client.disconnect() try: loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait_for(client.connect(on_connect_callback=on_connect, on_receive_message_callback=on_message), WEBSOCKET_TIMEOUT_GET_REQUEST)) except asyncio.TimeoutError: raise TimeoutError("Test did not complete in time.") if not self.response: raise RuntimeError("Did not receive a response.") self.assertDictStructure(expect, self.response)
from tradehub.websocket_client import DemexWebsocket import asyncio async def on_connect(): print("I am connect to demex websocket!") await demex.subscribe_books("orderbook", "swth_eth1") async def on_receive_message(message: dict): print("I received a message") print(message) if __name__ == '__main__': demex: DemexWebsocket = DemexWebsocket('ws://164.132.169.19:5000/ws') asyncio.get_event_loop().run_until_complete( demex.connect(on_receive_message, on_connect))
def test_get_order_history_structure(self): """ Check if response match expected dict structure. :return: """ expect: dict = { "id": str, "result": [{ "order_id": str, "block_height": int, "triggered_block_height": int, "address": str, "market": str, "side": str, "price": str, "quantity": str, "available": str, "filled": str, "order_status": str, "order_type": str, "initiator": str, "time_in_force": str, "stop_price": str, "trigger_type": str, "allocated_margin_denom": str, "allocated_margin_amount": str, "is_liquidation": bool, "is_post_only": bool, "is_reduce_only": bool, "type": str, "block_created_at": str, "username": str, "id": str, }] } # connect to websocket client = DemexWebsocket(uri=MAINNET_WS_URI) # little work around to save the response self.response: Optional[dict] = None async def on_connect(): await client.get_order_history('order_history', WALLET_DEVEL) async def on_message(message: dict): # save response into self self.response = message await client.disconnect() try: loop = asyncio.get_event_loop() loop.run_until_complete( asyncio.wait_for( client.connect(on_connect_callback=on_connect, on_receive_message_callback=on_message), WEBSOCKET_TIMEOUT_GET_REQUEST)) except asyncio.TimeoutError: raise TimeoutError("Test did not complete in time.") if not self.response: raise RuntimeError("Did not receive a response.") self.assertDictStructure(expect, self.response)
def test_subscribe_candlesticks_structure(self): """ Check if response match expected dict structure. :return: """ expect_subscription: dict = {'id': str, 'result': [str]} expect: dict = { 'channel': str, 'sequence_number': int, 'result': { 'id': int, 'market': str, 'time': str, 'resolution': int, 'open': str, 'close': str, 'high': str, 'low': str, 'volume': str, 'quote_volume': str, } } # connect to websocket client = DemexWebsocket(uri=MAINNET_WS_URI) # little work around to save the response self.response: List[dict] = [] async def on_connect(): await client.subscribe_candlesticks('candlesticks', "swth_eth1", 1) async def on_message(message: dict): # save response into self print(message) self.response.append(message) try: loop = asyncio.get_event_loop() loop.run_until_complete( asyncio.wait_for( client.connect(on_connect_callback=on_connect, on_receive_message_callback=on_message), 2 * WEBSOCKET_TIMEOUT_SUBSCRIPTION)) except asyncio.TimeoutError: loop = asyncio.get_event_loop() loop.run_until_complete(client.disconnect()) if not self.response: raise RuntimeError("Did not receive a response.") if len(self.response) < 2: self.skipTest( f"Did not receive candlesticks within time, test can not finish." ) channel_subscription: dict = self.response[0] self.assertDictStructure(expect_subscription, channel_subscription) for message in self.response[1:]: if message["result"]: self.assertDictStructure(expect, message)
def test_subscribe_balance_structure(self): """ Check if response match expected dict structure. :return: """ expect_subscription: dict = {'id': str, 'result': [str]} balance: dict = { 'available': str, 'order': str, 'position': str, 'denom': str } expect: dict = { 'channel': str, 'result': { 'eth1': balance, 'eth1-80-swth-20-lp1': balance, 'swth': balance } } # connect to websocket client = DemexWebsocket(uri=MAINNET_WS_URI) # little work around to save the response self.response: List[dict] = [] async def on_connect(): # use AMM to be sure deterministic of which tokens the wallet holds await client.subscribe_balances('balance', WALLET_SWTH_ETH1_AMM) async def on_message(message: dict): # save response into self self.response.append(message) try: loop = asyncio.get_event_loop() loop.run_until_complete( asyncio.wait_for( client.connect(on_connect_callback=on_connect, on_receive_message_callback=on_message), WEBSOCKET_TIMEOUT_SUBSCRIPTION)) except asyncio.TimeoutError: loop = asyncio.get_event_loop() loop.run_until_complete(client.disconnect()) if not self.response: raise RuntimeError("Did not receive a response.") self.assertTrue( len(self.response) >= 2, msg= f"Expected at least 2 messages: channel subscription and and first update message" ) channel_subscription: dict = self.response[0] self.assertDictStructure(expect_subscription, channel_subscription) for message in self.response[1:]: # if this fails, check if the AMM wallet own other tokens as expected self.assertDictStructure(expect, message)
def test_subscribe_market_stats_structure(self): """ Check if response match expected dict structure. :return: """ expect_subscription: dict = {'id': str, 'result': [str]} market_stats: dict = { "day_high": str, "day_low": str, "day_open": str, "day_close": str, "day_volume": str, "day_quote_volume": str, "index_price": str, "mark_price": str, "last_price": str, "market": str, "market_type": str, "open_interest": str } expect: dict = { 'channel': str, 'sequence_number': int, 'result': { 'cel1_usdc1': market_stats, 'eth1_usdc1': market_stats, 'eth1_wbtc1': market_stats, 'nex1_usdc1': market_stats, 'nneo2_usdc1': market_stats, 'swth_eth1': market_stats, 'swth_usdc1': market_stats, 'wbtc1_usdc1': market_stats, 'btc_h21': market_stats, 'eth_h21': market_stats, } } # connect to websocket client = DemexWebsocket(uri=MAINNET_WS_URI) # little work around to save the response self.response: List[dict] = [] async def on_connect(): await client.subscribe_market_stats('market_stats') async def on_message(message: dict): # save response into self self.response.append(message) try: loop = asyncio.get_event_loop() loop.run_until_complete( asyncio.wait_for( client.connect(on_connect_callback=on_connect, on_receive_message_callback=on_message), WEBSOCKET_TIMEOUT_GET_REQUEST)) except asyncio.TimeoutError: loop = asyncio.get_event_loop() loop.run_until_complete(client.disconnect()) if not self.response: raise RuntimeError("Did not receive a response.") if len(self.response) < 2: self.skipTest( f"Did not receive candlesticks within time, test can not finish." ) channel_subscription: dict = self.response[0] self.assertDictStructure(expect_subscription, channel_subscription) for message in self.response[1:]: self.assertDictStructure(expect, message)