From ff22ea27b62fb761dfc0babe2a74534465bbecef Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Sat, 7 Dec 2024 16:09:46 +0100 Subject: [PATCH 1/2] [Tests] add test_is_authenticated_request tests --- additional_tests/exchanges_tests/__init__.py | 5 +- .../abstract_authenticated_exchange_tester.py | 110 +++++++++++++++++- .../exchanges_tests/test_ascendex.py | 3 + .../exchanges_tests/test_binance.py | 5 + .../exchanges_tests/test_binance_futures.py | 4 + .../exchanges_tests/test_bingx.py | 4 + .../exchanges_tests/test_bitget.py | 3 + .../exchanges_tests/test_bitmart.py | 3 + .../exchanges_tests/test_bybit.py | 3 + .../exchanges_tests/test_bybit_futures.py | 3 + .../exchanges_tests/test_coinbase.py | 4 + .../exchanges_tests/test_coinex.py | 3 + .../exchanges_tests/test_cryptocom.py | 3 + .../exchanges_tests/test_gateio.py | 3 + .../exchanges_tests/test_hollaex.py | 3 + additional_tests/exchanges_tests/test_htx.py | 3 + .../exchanges_tests/test_kucoin.py | 4 + .../exchanges_tests/test_kucoin_futures.py | 4 + additional_tests/exchanges_tests/test_mexc.py | 3 + additional_tests/exchanges_tests/test_okx.py | 4 + .../exchanges_tests/test_okx_futures.py | 3 + .../exchanges_tests/test_phemex.py | 3 + 22 files changed, 179 insertions(+), 4 deletions(-) diff --git a/additional_tests/exchanges_tests/__init__.py b/additional_tests/exchanges_tests/__init__.py index f351a2809..5f88a1b6e 100644 --- a/additional_tests/exchanges_tests/__init__.py +++ b/additional_tests/exchanges_tests/__init__.py @@ -65,7 +65,7 @@ def get_name(self): async def get_authenticated_exchange_manager( exchange_name, exchange_tentacle_name, config=None, credentials_exchange_name=None, market_filter=None, - use_invalid_creds=False + use_invalid_creds=False, http_proxy_callback_factory=None ): credentials_exchange_name = credentials_exchange_name or exchange_name _load_exchange_creds_env_variables_if_necessary() @@ -89,6 +89,9 @@ async def get_authenticated_exchange_manager( .enable_storage(False) \ .disable_trading_mode() \ .is_exchange_only() + if http_proxy_callback_factory: + proxy_callback = http_proxy_callback_factory(exchange_builder.exchange_manager) + exchange_builder.set_proxy_config(exchanges.ProxyConfig(http_proxy_callback=proxy_callback)) exchange_manager_instance = await exchange_builder.build() # create trader afterwards to init exchange personal data exchange_manager_instance.trader.is_enabled = True diff --git a/additional_tests/exchanges_tests/abstract_authenticated_exchange_tester.py b/additional_tests/exchanges_tests/abstract_authenticated_exchange_tester.py index 257021f92..ce69c697d 100644 --- a/additional_tests/exchanges_tests/abstract_authenticated_exchange_tester.py +++ b/additional_tests/exchanges_tests/abstract_authenticated_exchange_tester.py @@ -17,11 +17,13 @@ import contextlib import decimal import time - +import typing +import ccxt import mock import pytest import octobot_commons.constants as constants +import octobot_commons.enums as commons_enums import octobot_commons.symbols as symbols import octobot_trading.errors as trading_errors import octobot_trading.enums as trading_enums @@ -80,6 +82,7 @@ class AbstractAuthenticatedExchangeTester: MAX_TRADE_USD_VALUE = decimal.Decimal(8000) MIN_TRADE_USD_VALUE = decimal.Decimal("0.1") IS_ACCOUNT_ID_AVAILABLE = True # set False when get_account_id is not available and should be checked + IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE = False # set True when is_authenticated_request is implemented EXPECTED_GENERATED_ACCOUNT_ID = False # set True when account_id can't be fetch and a generated account id is used USE_ORDER_OPERATION_TO_CHECK_API_KEY_RIGHTS = False # set True when api key rights can't be checked using a # dedicated api and have to be checked by sending an order operation @@ -142,7 +145,7 @@ async def test_get_account_id(self): await self.inner_test_get_account_id() async def inner_test_get_account_id(self): - if self.IS_ACCOUNT_ID_AVAILABLE: + if self.IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE: account_id = await self.exchange_manager.exchange.get_account_id() assert account_id assert isinstance(account_id, str) @@ -154,6 +157,104 @@ async def inner_test_get_account_id(self): with pytest.raises(NotImplementedError): await self.exchange_manager.exchange.get_account_id() + async def test_is_authenticated_request(self): + rest_exchange_data = { + "calls": [], + } + def _http_proxy_callback_factory(_exchange_manager): + rest_exchange_data["exchange_manager"] = _exchange_manager + def proxy_callback(url: str, method: str, headers: dict, body) -> typing.Optional[str]: + if not self.IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE: + return None + if "rest_exchange" not in rest_exchange_data: + rest_exchange_data["rest_exchange"] = rest_exchange_data["exchange_manager"].exchange + rest_exchange = rest_exchange_data["rest_exchange"] + exchange_return_value = rest_exchange.is_authenticated_request(url, method, headers, body) + rest_exchange_data["calls"].append( + ((url, method, headers, body), exchange_return_value) + ) + # never return any proxy url: no proxy is set but make sure to register each request call + return None + + return proxy_callback + + async with self.local_exchange_manager(http_proxy_callback_factory=_http_proxy_callback_factory): + await self.inner_is_authenticated_request(rest_exchange_data) + + async def inner_is_authenticated_request(self, rest_exchange_data): + if self.IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE: + latest_call_indexes = [len(rest_exchange_data["calls"])] + def get_latest_calls(): + latest_calls = rest_exchange_data["calls"][latest_call_indexes[-1]:] + latest_call_indexes.append(len(rest_exchange_data["calls"])) + return latest_calls + + def assert_has_at_least_one_authenticated_call(calls): + has_authenticated_call = False + for latest_call in calls: + # should be at least 1 authenticated call + if latest_call[1] is True: + has_authenticated_call = True + assert has_authenticated_call, f"{calls} should contain at last 1 authenticated call" # authenticated request + + # 1. test using different values + assert self.exchange_manager.exchange.is_authenticated_request("", "", {}, None) is False + assert self.exchange_manager.exchange.is_authenticated_request("", "", {}, "") is False + assert self.exchange_manager.exchange.is_authenticated_request("", "", {}, b"") is False + assert self.exchange_manager.exchange.is_authenticated_request(None, None, None, b"") is False + + # 2. make public requests + assert await self.exchange_manager.exchange.get_symbol_prices( + self.SYMBOL, commons_enums.TimeFrames.ONE_HOUR + ) + latest_calls = get_latest_calls() + for latest_call in latest_calls: + assert latest_call[1] is False, f"{latest_call} should be NOT authenticated" # authenticated request + ticker = await self.exchange_manager.exchange.get_price_ticker(self.SYMBOL) + assert ticker + last_price = ticker[trading_enums.ExchangeConstantsTickersColumns.CLOSE.value] + assert rest_exchange_data["calls"][-1][0][0] != latest_calls[-1][0][0] # assert latest call's url changed + latest_calls = get_latest_calls() + for latest_call in latest_calls: + assert latest_call[1] is False, f"{latest_call} should be NOT authenticated" # authenticated request + + # 3. make private requests + # balance (usually a GET) + portfolio = await self.get_portfolio() + if self.CHECK_EMPTY_ACCOUNT: + assert portfolio == {} + else: + assert portfolio + assert rest_exchange_data["calls"][-1][0][0] != latest_calls[-1][0][0] # assert latest call's url changed + latest_calls = get_latest_calls() + assert_has_at_least_one_authenticated_call(latest_calls) + # create order (usually a POST) + price = decimal.Decimal(str(last_price)) * decimal.Decimal("0.7") + amount = self.get_order_size( + portfolio, price, symbol=self.SYMBOL, settlement_currency=self.SETTLEMENT_CURRENCY + ) * 100000 + if self.CHECK_EMPTY_ACCOUNT: + amount = 10 + # (amount is too large, creating buy order will fail) + with pytest.raises(ccxt.ExchangeError): + await self.exchange_manager.exchange.connector.create_limit_buy_order( + self.SYMBOL, amount, price=price, params={} + ) + assert rest_exchange_data["calls"][-1][0][0] != latest_calls[-1][0][0] # assert latest call's url changed + latest_calls = get_latest_calls() + assert_has_at_least_one_authenticated_call(latest_calls) + # cancel order (usually a DELETE) + with pytest.raises(ccxt.BaseError): + # use client call directly to avoid any octobot error conversion + await self.exchange_manager.exchange.connector.client.cancel_order(self.VALID_ORDER_ID, self.SYMBOL) + assert rest_exchange_data["calls"][-1][0][0] != latest_calls[-1][0][0] # assert latest call's url changed + latest_calls = get_latest_calls() + assert_has_at_least_one_authenticated_call(latest_calls) + else: + with pytest.raises(NotImplementedError): + self.exchange_manager.exchange.is_authenticated_request("", "", {}, None) + await asyncio.sleep(1.5) # let initial requests finish to be able to stop exchange manager + async def test_invalid_api_key_error(self): with pytest.raises(trading_errors.AuthenticationError): created_exchange = mock.Mock() @@ -787,7 +888,9 @@ async def get_price(self, symbol=None): )) @contextlib.asynccontextmanager - async def local_exchange_manager(self, market_filter=None, identifiers_suffix=None, use_invalid_creds=False): + async def local_exchange_manager( + self, market_filter=None, identifiers_suffix=None, use_invalid_creds=False, http_proxy_callback_factory=None + ): try: exchange_tentacle_name = self.EXCHANGE_TENTACLE_NAME or self.EXCHANGE_NAME.capitalize() credentials_exchange_name = self.CREDENTIALS_EXCHANGE_NAME or self.EXCHANGE_NAME @@ -800,6 +903,7 @@ async def local_exchange_manager(self, market_filter=None, identifiers_suffix=No credentials_exchange_name=credentials_exchange_name, market_filter=market_filter, use_invalid_creds=use_invalid_creds, + http_proxy_callback_factory=http_proxy_callback_factory, ) as exchange_manager: self.exchange_manager = exchange_manager yield diff --git a/additional_tests/exchanges_tests/test_ascendex.py b/additional_tests/exchanges_tests/test_ascendex.py index aff455acf..f43b2800d 100644 --- a/additional_tests/exchanges_tests/test_ascendex.py +++ b/additional_tests/exchanges_tests/test_ascendex.py @@ -44,6 +44,9 @@ async def test_get_account_id(self): # pass if not implemented pass + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_binance.py b/additional_tests/exchanges_tests/test_binance.py index 9bd62ca14..225e787a9 100644 --- a/additional_tests/exchanges_tests/test_binance.py +++ b/additional_tests/exchanges_tests/test_binance.py @@ -39,6 +39,8 @@ class TestBinanceAuthenticatedExchange( '7457370420', ] IS_BROKER_ENABLED_ACCOUNT = False + IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE = True # set True when is_authenticated_request is implemented + async def test_get_portfolio(self): await super().test_get_portfolio() @@ -49,6 +51,9 @@ async def test_get_portfolio_with_market_filter(self): async def test_get_account_id(self): await super().test_get_account_id() + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_binance_futures.py b/additional_tests/exchanges_tests/test_binance_futures.py index cfb5c6ce7..d4e26b8fb 100644 --- a/additional_tests/exchanges_tests/test_binance_futures.py +++ b/additional_tests/exchanges_tests/test_binance_futures.py @@ -36,6 +36,7 @@ class TestBinanceFuturesAuthenticatedExchange( DUPLICATE_TRADES_RATIO = 0.1 # allow 10% duplicate in trades (due to trade id set to order id) VALID_ORDER_ID = "26408108410" EXPECTED_QUOTE_MIN_ORDER_SIZE = 200 # min quote value of orders to create (used to check market status parsing) + IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE = True # set True when is_authenticated_request is implemented async def _set_account_types(self, account_types): # todo remove this and use both types when exchange-side multi portfolio is enabled @@ -51,6 +52,9 @@ async def test_get_portfolio_with_market_filter(self): async def test_get_account_id(self): await super().test_get_account_id() + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_bingx.py b/additional_tests/exchanges_tests/test_bingx.py index 3150a9f44..71f2e0d94 100644 --- a/additional_tests/exchanges_tests/test_bingx.py +++ b/additional_tests/exchanges_tests/test_bingx.py @@ -34,6 +34,7 @@ class TestBingxAuthenticatedExchange( IGNORE_EXCHANGE_TRADE_ID = True USE_ORDER_OPERATION_TO_CHECK_API_KEY_RIGHTS = True EXPECT_MISSING_FEE_IN_CANCELLED_ORDERS = False + IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE = True # set True when is_authenticated_request is implemented VALID_ORDER_ID = "1812980957928929280" @@ -46,6 +47,9 @@ async def test_get_portfolio_with_market_filter(self): async def test_get_account_id(self): await super().test_get_account_id() + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_bitget.py b/additional_tests/exchanges_tests/test_bitget.py index a670a1d6d..33c03e91d 100644 --- a/additional_tests/exchanges_tests/test_bitget.py +++ b/additional_tests/exchanges_tests/test_bitget.py @@ -46,6 +46,9 @@ async def test_get_account_id(self): # pass if not implemented pass + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_bitmart.py b/additional_tests/exchanges_tests/test_bitmart.py index b0e1a87c2..f1eacab34 100644 --- a/additional_tests/exchanges_tests/test_bitmart.py +++ b/additional_tests/exchanges_tests/test_bitmart.py @@ -44,6 +44,9 @@ async def test_get_account_id(self): # pass if not implemented pass + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_bybit.py b/additional_tests/exchanges_tests/test_bybit.py index 40e0d13cc..1eb4dde3c 100644 --- a/additional_tests/exchanges_tests/test_bybit.py +++ b/additional_tests/exchanges_tests/test_bybit.py @@ -48,6 +48,9 @@ async def test_get_account_id(self): # pass if not implemented pass + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_bybit_futures.py b/additional_tests/exchanges_tests/test_bybit_futures.py index 72a245b8a..950b07c0b 100644 --- a/additional_tests/exchanges_tests/test_bybit_futures.py +++ b/additional_tests/exchanges_tests/test_bybit_futures.py @@ -51,6 +51,9 @@ async def test_get_account_id(self): # pass if not implemented pass + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_coinbase.py b/additional_tests/exchanges_tests/test_coinbase.py index d98e37c1b..26f923c53 100644 --- a/additional_tests/exchanges_tests/test_coinbase.py +++ b/additional_tests/exchanges_tests/test_coinbase.py @@ -35,6 +35,7 @@ class TestCoinbaseAuthenticatedExchange( USE_ORDER_OPERATION_TO_CHECK_API_KEY_RIGHTS = True # set True when api key rights can't be checked using a EXPECT_MISSING_FEE_IN_CANCELLED_ORDERS = False IS_BROKER_ENABLED_ACCOUNT = False + IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE = True # set True when is_authenticated_request is implemented async def test_get_portfolio(self): await super().test_get_portfolio() @@ -45,6 +46,9 @@ async def test_get_portfolio_with_market_filter(self): async def test_get_account_id(self): await super().test_get_account_id() + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_coinex.py b/additional_tests/exchanges_tests/test_coinex.py index 780bad832..d4fa0a9c1 100644 --- a/additional_tests/exchanges_tests/test_coinex.py +++ b/additional_tests/exchanges_tests/test_coinex.py @@ -43,6 +43,9 @@ async def test_get_account_id(self): # pass if not implemented pass + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_cryptocom.py b/additional_tests/exchanges_tests/test_cryptocom.py index 1a567fe39..7963937b9 100644 --- a/additional_tests/exchanges_tests/test_cryptocom.py +++ b/additional_tests/exchanges_tests/test_cryptocom.py @@ -44,6 +44,9 @@ async def test_get_account_id(self): # pass if not implemented pass + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_gateio.py b/additional_tests/exchanges_tests/test_gateio.py index 97d8df012..d5cf41b7e 100644 --- a/additional_tests/exchanges_tests/test_gateio.py +++ b/additional_tests/exchanges_tests/test_gateio.py @@ -45,6 +45,9 @@ async def test_get_account_id(self): # pass if not implemented pass + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): # await super().test_invalid_api_key_error() # raises Request timeout pass diff --git a/additional_tests/exchanges_tests/test_hollaex.py b/additional_tests/exchanges_tests/test_hollaex.py index d9bcdee7d..be63620b9 100644 --- a/additional_tests/exchanges_tests/test_hollaex.py +++ b/additional_tests/exchanges_tests/test_hollaex.py @@ -47,6 +47,9 @@ async def test_get_portfolio_with_market_filter(self): async def test_get_account_id(self): await super().test_get_account_id() + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_htx.py b/additional_tests/exchanges_tests/test_htx.py index 6477fb886..a22c17725 100644 --- a/additional_tests/exchanges_tests/test_htx.py +++ b/additional_tests/exchanges_tests/test_htx.py @@ -45,6 +45,9 @@ async def test_get_account_id(self): # pass if not implemented pass + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_kucoin.py b/additional_tests/exchanges_tests/test_kucoin.py index e6d18f404..3a0f6c3f0 100644 --- a/additional_tests/exchanges_tests/test_kucoin.py +++ b/additional_tests/exchanges_tests/test_kucoin.py @@ -34,6 +34,7 @@ class TestKucoinAuthenticatedExchange( EXPECTED_GENERATED_ACCOUNT_ID = False # True when subaccounts are created USE_ORDER_OPERATION_TO_CHECK_API_KEY_RIGHTS = True VALID_ORDER_ID = "6617e84c5c1e0000083c71f7" + IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE = True # set True when is_authenticated_request is implemented async def test_get_portfolio(self): await super().test_get_portfolio() @@ -50,6 +51,9 @@ async def test_create_and_cancel_limit_orders(self): async def test_get_account_id(self): await super().test_get_account_id() + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_kucoin_futures.py b/additional_tests/exchanges_tests/test_kucoin_futures.py index 7c31e6e32..781259d94 100644 --- a/additional_tests/exchanges_tests/test_kucoin_futures.py +++ b/additional_tests/exchanges_tests/test_kucoin_futures.py @@ -37,6 +37,7 @@ class TestKucoinFuturesAuthenticatedExchange( USE_ORDER_OPERATION_TO_CHECK_API_KEY_RIGHTS = True VALID_ORDER_ID = "6617e84c5c1e0000083c71f7" EXPECT_MISSING_FEE_IN_CANCELLED_ORDERS = False + IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE = True # set True when is_authenticated_request is implemented async def test_get_portfolio(self): await super().test_get_portfolio() @@ -48,6 +49,9 @@ async def test_get_portfolio_with_market_filter(self): async def test_get_account_id(self): await super().test_get_account_id() + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_mexc.py b/additional_tests/exchanges_tests/test_mexc.py index 72f87e599..a47659703 100644 --- a/additional_tests/exchanges_tests/test_mexc.py +++ b/additional_tests/exchanges_tests/test_mexc.py @@ -45,6 +45,9 @@ async def test_get_account_id(self): # pass if not implemented pass + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_okx.py b/additional_tests/exchanges_tests/test_okx.py index fb8aeb4d3..632cceaf2 100644 --- a/additional_tests/exchanges_tests/test_okx.py +++ b/additional_tests/exchanges_tests/test_okx.py @@ -34,6 +34,7 @@ class TestOKXAuthenticatedExchange( VALID_ORDER_ID = "698652818181726221" CHECK_EMPTY_ACCOUNT = True # set True when the account to check has no funds. Warning: does not check order # parse/create/fill/cancel or portfolio & trades parsing + IS_AUTHENTICATED_REQUEST_CHECK_AVAILABLE = True # set True when is_authenticated_request is implemented async def test_get_portfolio(self): await super().test_get_portfolio() @@ -50,6 +51,9 @@ async def test_create_and_cancel_limit_orders(self): async def test_get_account_id(self): await super().test_get_account_id() + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_okx_futures.py b/additional_tests/exchanges_tests/test_okx_futures.py index 95dfbf7b1..656efb7a9 100644 --- a/additional_tests/exchanges_tests/test_okx_futures.py +++ b/additional_tests/exchanges_tests/test_okx_futures.py @@ -46,6 +46,9 @@ async def test_get_portfolio_with_market_filter(self): async def test_get_account_id(self): await super().test_get_account_id() + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() diff --git a/additional_tests/exchanges_tests/test_phemex.py b/additional_tests/exchanges_tests/test_phemex.py index 5f82b302f..b570e3bd8 100644 --- a/additional_tests/exchanges_tests/test_phemex.py +++ b/additional_tests/exchanges_tests/test_phemex.py @@ -43,6 +43,9 @@ async def test_get_account_id(self): # pass if not implemented pass + async def test_is_authenticated_request(self): + await super().test_is_authenticated_request() + async def test_invalid_api_key_error(self): await super().test_invalid_api_key_error() From b7c897bfe474aa3becc281c9b6e3f988cd85e2d3 Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Sat, 7 Dec 2024 16:10:18 +0100 Subject: [PATCH 2/2] [Requirements] bump --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index eec00f9b6..e8a9a1484 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # Drakkar-Software requirements -OctoBot-Commons==1.9.68 -OctoBot-Trading==2.4.130 +OctoBot-Commons==1.9.69 +OctoBot-Trading==2.4.131 OctoBot-Evaluators==1.9.7 OctoBot-Tentacles-Manager==2.9.16 OctoBot-Services==1.6.21