From a806a5ee6999036e2dbfa6b685e5e2f54587867f Mon Sep 17 00:00:00 2001 From: Abel Armoa <30988000+aarmoa@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:34:01 -0300 Subject: [PATCH 1/3] (fix) Fixed the v1 AsyncClient orderbooks queries to include the depth parameter --- CHANGELOG.md | 7 +++ pyinjective/async_client.py | 22 ++++--- pyproject.toml | 2 +- .../test_async_client_deprecation_warnings.py | 59 +++++++++++++++++++ 4 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 tests/test_async_client_deprecation_warnings.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ad72282..cee1e91f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. +## [1.11.1] - 2025-08-20 +### Changed +- Marked the v1 AsyncClient as deprecated + +### Fixed +- Fixed the Indexer orderbooks queries in the v1 AsyncClient to include the depth parameter + ## [1.11.0] - 2025-07-29 ### Added - Added support for Exchange V2 proto queries and types diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index 31f41a9d..c310fc75 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -58,6 +58,12 @@ def __init__( self, network: Network, ): + warn( + "AsyncClient from pyinjective.async_client is deprecated. " + "Please use AsyncClient from pyinjective.async_client_v2 instead.", + DeprecationWarning, + stacklevel=2, + ) self.addr = "" self.number = 0 self.sequence = 0 @@ -1337,11 +1343,11 @@ async def listen_spot_markets_updates( market_ids=market_ids, ) - async def fetch_spot_orderbook_v2(self, market_id: str) -> Dict[str, Any]: - return await self.indexer_client.fetch_spot_orderbook_v2(market_id=market_id) + async def fetch_spot_orderbook_v2(self, market_id: str, depth: Optional[int] = None) -> Dict[str, Any]: + return await self.indexer_client.fetch_spot_orderbook_v2(market_id=market_id, depth=depth or 0) - async def fetch_spot_orderbooks_v2(self, market_ids: List[str]) -> Dict[str, Any]: - return await self.indexer_client.fetch_spot_orderbooks_v2(market_ids=market_ids) + async def fetch_spot_orderbooks_v2(self, market_ids: List[str], depth: Optional[int] = None) -> Dict[str, Any]: + return await self.indexer_client.fetch_spot_orderbooks_v2(market_ids=market_ids, depth=depth or 0) async def fetch_spot_orders( self, @@ -1608,11 +1614,11 @@ async def listen_derivative_market_updates( market_ids=market_ids, ) - async def fetch_derivative_orderbook_v2(self, market_id: str) -> Dict[str, Any]: - return await self.indexer_client.fetch_derivative_orderbook_v2(market_id=market_id) + async def fetch_derivative_orderbook_v2(self, market_id: str, depth: Optional[int] = None) -> Dict[str, Any]: + return await self.indexer_client.fetch_derivative_orderbook_v2(market_id=market_id, depth=depth or 0) - async def fetch_derivative_orderbooks_v2(self, market_ids: List[str]) -> Dict[str, Any]: - return await self.indexer_client.fetch_derivative_orderbooks_v2(market_ids=market_ids) + async def fetch_derivative_orderbooks_v2(self, market_ids: List[str], depth: Optional[int] = None) -> Dict[str, Any]: + return await self.indexer_client.fetch_derivative_orderbooks_v2(market_ids=market_ids, depth=depth or 0) async def fetch_derivative_orders( self, diff --git a/pyproject.toml b/pyproject.toml index 1d607918..0ba95f7a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "injective-py" -version = "1.11.0" +version = "1.11.1" description = "Injective Python SDK, with Exchange API Client" authors = ["Injective Labs "] license = "Apache-2.0" diff --git a/tests/test_async_client_deprecation_warnings.py b/tests/test_async_client_deprecation_warnings.py new file mode 100644 index 00000000..9a896d69 --- /dev/null +++ b/tests/test_async_client_deprecation_warnings.py @@ -0,0 +1,59 @@ +import warnings +from unittest.mock import MagicMock, patch + +import pytest + +from pyinjective.core.network import Network + + +class TestAsyncClientDeprecationWarnings: + def test_async_client_deprecation_warning(self): + """Test that creating an AsyncClient instance raises a deprecation warning with correct details.""" + with patch('pyinjective.async_client.IndexerClient'), \ + patch('pyinjective.async_client.ChainGrpcBankApi'), \ + patch('pyinjective.async_client.ChainGrpcAuthApi'), \ + patch('pyinjective.async_client.ChainGrpcAuthZApi'), \ + patch('pyinjective.async_client.ChainGrpcDistributionApi'), \ + patch('pyinjective.async_client.ChainGrpcExchangeApi'), \ + patch('pyinjective.async_client.ChainGrpcChainStream'), \ + patch('pyinjective.async_client.asyncio.get_event_loop'): + + # Create a mock network to avoid actual network initialization + mock_network = MagicMock(spec=Network) + mock_network.chain_cookie_assistant = MagicMock() + mock_network.create_chain_grpc_channel = MagicMock() + mock_network.create_chain_stream_grpc_channel = MagicMock() + mock_network.official_tokens_list_url = "https://example.com/tokens.json" + + # Import here to avoid early import issues + from pyinjective.async_client import AsyncClient + + # Capture warnings + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") # Ensure all warnings are captured + + # Create AsyncClient instance - this should trigger the deprecation warning + client = AsyncClient(network=mock_network) + + # Find the AsyncClient deprecation warning + async_client_warnings = [ + w for w in warning_list + if issubclass(w.category, DeprecationWarning) and + "AsyncClient from pyinjective.async_client is deprecated" in str(w.message) + ] + + # Should have exactly one warning + assert len(async_client_warnings) == 1 + + warning = async_client_warnings[0] + # Check warning message contains migration advice + assert "Please use AsyncClient from pyinjective.async_client_v2 instead" in str(warning.message) + # Check warning category + assert warning.category == DeprecationWarning + # Check stacklevel is working correctly (should point to this test file) + assert "test_async_client_deprecation_warnings.py" in warning.filename + + # Verify the client was still created successfully + assert client is not None + assert hasattr(client, 'network') + assert client.network == mock_network From cc2942843aa386d8060e4ed21225b95b305afdcc Mon Sep 17 00:00:00 2001 From: Abel Armoa <30988000+aarmoa@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:51:59 -0300 Subject: [PATCH 2/3] (fix) Fixed pre-commit errors --- pyinjective/async_client.py | 4 +- .../test_async_client_deprecation_warnings.py | 100 +++++++++--------- ...est_indexer_client_deprecation_warnings.py | 81 ++++++++++++++ 3 files changed, 133 insertions(+), 52 deletions(-) create mode 100644 tests/test_indexer_client_deprecation_warnings.py diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index c310fc75..dd0fc7ff 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -1617,7 +1617,9 @@ async def listen_derivative_market_updates( async def fetch_derivative_orderbook_v2(self, market_id: str, depth: Optional[int] = None) -> Dict[str, Any]: return await self.indexer_client.fetch_derivative_orderbook_v2(market_id=market_id, depth=depth or 0) - async def fetch_derivative_orderbooks_v2(self, market_ids: List[str], depth: Optional[int] = None) -> Dict[str, Any]: + async def fetch_derivative_orderbooks_v2( + self, market_ids: List[str], depth: Optional[int] = None + ) -> Dict[str, Any]: return await self.indexer_client.fetch_derivative_orderbooks_v2(market_ids=market_ids, depth=depth or 0) async def fetch_derivative_orders( diff --git a/tests/test_async_client_deprecation_warnings.py b/tests/test_async_client_deprecation_warnings.py index 9a896d69..c17481fe 100644 --- a/tests/test_async_client_deprecation_warnings.py +++ b/tests/test_async_client_deprecation_warnings.py @@ -1,59 +1,57 @@ import warnings from unittest.mock import MagicMock, patch -import pytest - from pyinjective.core.network import Network class TestAsyncClientDeprecationWarnings: - def test_async_client_deprecation_warning(self): + @patch("pyinjective.async_client.asyncio.get_event_loop") + @patch("pyinjective.async_client.ChainGrpcChainStream") + @patch("pyinjective.async_client.ChainGrpcExchangeApi") + @patch("pyinjective.async_client.ChainGrpcDistributionApi") + @patch("pyinjective.async_client.ChainGrpcAuthZApi") + @patch("pyinjective.async_client.ChainGrpcAuthApi") + @patch("pyinjective.async_client.ChainGrpcBankApi") + @patch("pyinjective.async_client.IndexerClient") + def test_async_client_deprecation_warning(self, *mocks): """Test that creating an AsyncClient instance raises a deprecation warning with correct details.""" - with patch('pyinjective.async_client.IndexerClient'), \ - patch('pyinjective.async_client.ChainGrpcBankApi'), \ - patch('pyinjective.async_client.ChainGrpcAuthApi'), \ - patch('pyinjective.async_client.ChainGrpcAuthZApi'), \ - patch('pyinjective.async_client.ChainGrpcDistributionApi'), \ - patch('pyinjective.async_client.ChainGrpcExchangeApi'), \ - patch('pyinjective.async_client.ChainGrpcChainStream'), \ - patch('pyinjective.async_client.asyncio.get_event_loop'): - - # Create a mock network to avoid actual network initialization - mock_network = MagicMock(spec=Network) - mock_network.chain_cookie_assistant = MagicMock() - mock_network.create_chain_grpc_channel = MagicMock() - mock_network.create_chain_stream_grpc_channel = MagicMock() - mock_network.official_tokens_list_url = "https://example.com/tokens.json" - - # Import here to avoid early import issues - from pyinjective.async_client import AsyncClient - - # Capture warnings - with warnings.catch_warnings(record=True) as warning_list: - warnings.simplefilter("always") # Ensure all warnings are captured - - # Create AsyncClient instance - this should trigger the deprecation warning - client = AsyncClient(network=mock_network) - - # Find the AsyncClient deprecation warning - async_client_warnings = [ - w for w in warning_list - if issubclass(w.category, DeprecationWarning) and - "AsyncClient from pyinjective.async_client is deprecated" in str(w.message) - ] - - # Should have exactly one warning - assert len(async_client_warnings) == 1 - - warning = async_client_warnings[0] - # Check warning message contains migration advice - assert "Please use AsyncClient from pyinjective.async_client_v2 instead" in str(warning.message) - # Check warning category - assert warning.category == DeprecationWarning - # Check stacklevel is working correctly (should point to this test file) - assert "test_async_client_deprecation_warnings.py" in warning.filename - - # Verify the client was still created successfully - assert client is not None - assert hasattr(client, 'network') - assert client.network == mock_network + # Create a mock network to avoid actual network initialization + mock_network = MagicMock(spec=Network) + mock_network.chain_cookie_assistant = MagicMock() + mock_network.create_chain_grpc_channel = MagicMock() + mock_network.create_chain_stream_grpc_channel = MagicMock() + mock_network.official_tokens_list_url = "https://example.com/tokens.json" + + # Import here to avoid early import issues + from pyinjective.async_client import AsyncClient + + # Capture warnings + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") # Ensure all warnings are captured + + # Create AsyncClient instance - this should trigger the deprecation warning + client = AsyncClient(network=mock_network) + + # Find the AsyncClient deprecation warning + async_client_warnings = [ + w + for w in warning_list + if issubclass(w.category, DeprecationWarning) + and "AsyncClient from pyinjective.async_client is deprecated" in str(w.message) + ] + + # Should have exactly one warning + assert len(async_client_warnings) == 1 + + warning = async_client_warnings[0] + # Check warning message contains migration advice + assert "Please use AsyncClient from pyinjective.async_client_v2 instead" in str(warning.message) + # Check warning category + assert warning.category == DeprecationWarning + # Check stacklevel is working correctly (should point to this test file) + assert "test_async_client_deprecation_warnings.py" in warning.filename + + # Verify the client was still created successfully + assert client is not None + assert hasattr(client, "network") + assert client.network == mock_network diff --git a/tests/test_indexer_client_deprecation_warnings.py b/tests/test_indexer_client_deprecation_warnings.py new file mode 100644 index 00000000..1ade61f1 --- /dev/null +++ b/tests/test_indexer_client_deprecation_warnings.py @@ -0,0 +1,81 @@ +import warnings +from unittest.mock import MagicMock, patch + +from pyinjective.core.network import Network + + +class TestIndexerClientDeprecationWarnings: + @patch("pyinjective.indexer_client.IndexerGrpcSpotStream") + @patch("pyinjective.indexer_client.IndexerGrpcPortfolioStream") + @patch("pyinjective.indexer_client.IndexerGrpcOracleStream") + @patch("pyinjective.indexer_client.IndexerGrpcMetaStream") + @patch("pyinjective.indexer_client.IndexerGrpcExplorerStream") + @patch("pyinjective.indexer_client.IndexerGrpcDerivativeStream") + @patch("pyinjective.indexer_client.IndexerGrpcAuctionStream") + @patch("pyinjective.indexer_client.IndexerGrpcAccountStream") + @patch("pyinjective.indexer_client.IndexerGrpcSpotApi") + @patch("pyinjective.indexer_client.IndexerGrpcPortfolioApi") + @patch("pyinjective.indexer_client.IndexerGrpcOracleApi") + @patch("pyinjective.indexer_client.IndexerGrpcMetaApi") + @patch("pyinjective.indexer_client.IndexerGrpcInsuranceApi") + @patch("pyinjective.indexer_client.IndexerGrpcExplorerApi") + @patch("pyinjective.indexer_client.IndexerGrpcDerivativeApi") + @patch("pyinjective.indexer_client.IndexerGrpcAuctionApi") + @patch("pyinjective.indexer_client.IndexerGrpcAccountApi") + def test_listen_derivative_positions_updates_deprecation_warning(self, *mocks): + """Test that calling listen_derivative_positions_updates raises a deprecation warning.""" + # Create a mock network to avoid actual network initialization + mock_network = MagicMock(spec=Network) + mock_network.exchange_cookie_assistant = MagicMock() + mock_network.explorer_cookie_assistant = MagicMock() + mock_network.create_exchange_grpc_channel = MagicMock() + mock_network.create_explorer_grpc_channel = MagicMock() + + # Import here to avoid early import issues + from pyinjective.indexer_client import IndexerClient + + # Create IndexerClient instance + client = IndexerClient(network=mock_network) + + # Mock the derivative_stream_api.stream_positions method to avoid actual streaming + client.derivative_stream_api.stream_positions = MagicMock() + + # Capture warnings + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") # Ensure all warnings are captured + + # Mock callback function + mock_callback = MagicMock() + + # Call the deprecated method - this should trigger the deprecation warning + client.listen_derivative_positions_updates( + callback=mock_callback, market_ids=["market_1"], subaccount_ids=["subaccount_1"] + ) + + # Find the deprecation warning + deprecation_warnings = [ + w + for w in warning_list + if issubclass(w.category, DeprecationWarning) + and "This method is deprecated. Use listen_derivative_positions_v2_updates instead" in str(w.message) + ] + + # Should have exactly one warning + assert len(deprecation_warnings) == 1 + + warning = deprecation_warnings[0] + # Check warning message contains migration advice + assert "Use listen_derivative_positions_v2_updates instead" in str(warning.message) + # Check warning category + assert warning.category == DeprecationWarning + # Check stacklevel is working correctly (should point to this test file) + assert "test_indexer_client_deprecation_warnings.py" in warning.filename + + # Verify the underlying method was still called (functionality preserved) + client.derivative_stream_api.stream_positions.assert_called_once_with( + callback=mock_callback, + on_end_callback=None, + on_status_callback=None, + market_ids=["market_1"], + subaccount_ids=["subaccount_1"], + ) From ff1921d91cd14d0f7d24c6157f6223d646f0b535 Mon Sep 17 00:00:00 2001 From: Abel Armoa <30988000+aarmoa@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:59:02 -0300 Subject: [PATCH 3/3] (fix) Fixed pre-commit errors --- ...est_indexer_client_deprecation_warnings.py | 81 ------------------- 1 file changed, 81 deletions(-) delete mode 100644 tests/test_indexer_client_deprecation_warnings.py diff --git a/tests/test_indexer_client_deprecation_warnings.py b/tests/test_indexer_client_deprecation_warnings.py deleted file mode 100644 index 1ade61f1..00000000 --- a/tests/test_indexer_client_deprecation_warnings.py +++ /dev/null @@ -1,81 +0,0 @@ -import warnings -from unittest.mock import MagicMock, patch - -from pyinjective.core.network import Network - - -class TestIndexerClientDeprecationWarnings: - @patch("pyinjective.indexer_client.IndexerGrpcSpotStream") - @patch("pyinjective.indexer_client.IndexerGrpcPortfolioStream") - @patch("pyinjective.indexer_client.IndexerGrpcOracleStream") - @patch("pyinjective.indexer_client.IndexerGrpcMetaStream") - @patch("pyinjective.indexer_client.IndexerGrpcExplorerStream") - @patch("pyinjective.indexer_client.IndexerGrpcDerivativeStream") - @patch("pyinjective.indexer_client.IndexerGrpcAuctionStream") - @patch("pyinjective.indexer_client.IndexerGrpcAccountStream") - @patch("pyinjective.indexer_client.IndexerGrpcSpotApi") - @patch("pyinjective.indexer_client.IndexerGrpcPortfolioApi") - @patch("pyinjective.indexer_client.IndexerGrpcOracleApi") - @patch("pyinjective.indexer_client.IndexerGrpcMetaApi") - @patch("pyinjective.indexer_client.IndexerGrpcInsuranceApi") - @patch("pyinjective.indexer_client.IndexerGrpcExplorerApi") - @patch("pyinjective.indexer_client.IndexerGrpcDerivativeApi") - @patch("pyinjective.indexer_client.IndexerGrpcAuctionApi") - @patch("pyinjective.indexer_client.IndexerGrpcAccountApi") - def test_listen_derivative_positions_updates_deprecation_warning(self, *mocks): - """Test that calling listen_derivative_positions_updates raises a deprecation warning.""" - # Create a mock network to avoid actual network initialization - mock_network = MagicMock(spec=Network) - mock_network.exchange_cookie_assistant = MagicMock() - mock_network.explorer_cookie_assistant = MagicMock() - mock_network.create_exchange_grpc_channel = MagicMock() - mock_network.create_explorer_grpc_channel = MagicMock() - - # Import here to avoid early import issues - from pyinjective.indexer_client import IndexerClient - - # Create IndexerClient instance - client = IndexerClient(network=mock_network) - - # Mock the derivative_stream_api.stream_positions method to avoid actual streaming - client.derivative_stream_api.stream_positions = MagicMock() - - # Capture warnings - with warnings.catch_warnings(record=True) as warning_list: - warnings.simplefilter("always") # Ensure all warnings are captured - - # Mock callback function - mock_callback = MagicMock() - - # Call the deprecated method - this should trigger the deprecation warning - client.listen_derivative_positions_updates( - callback=mock_callback, market_ids=["market_1"], subaccount_ids=["subaccount_1"] - ) - - # Find the deprecation warning - deprecation_warnings = [ - w - for w in warning_list - if issubclass(w.category, DeprecationWarning) - and "This method is deprecated. Use listen_derivative_positions_v2_updates instead" in str(w.message) - ] - - # Should have exactly one warning - assert len(deprecation_warnings) == 1 - - warning = deprecation_warnings[0] - # Check warning message contains migration advice - assert "Use listen_derivative_positions_v2_updates instead" in str(warning.message) - # Check warning category - assert warning.category == DeprecationWarning - # Check stacklevel is working correctly (should point to this test file) - assert "test_indexer_client_deprecation_warnings.py" in warning.filename - - # Verify the underlying method was still called (functionality preserved) - client.derivative_stream_api.stream_positions.assert_called_once_with( - callback=mock_callback, - on_end_callback=None, - on_status_callback=None, - market_ids=["market_1"], - subaccount_ids=["subaccount_1"], - )