Skip to content

Conversation

aarmoa
Copy link
Collaborator

@aarmoa aarmoa commented Aug 20, 2025

  • Fixed the v1 AsyncClient orderbooks queries to include the depth parameter
  • Marked the v1 AsyncClient as deprecated in favor of the v2 AsyncClient

Summary by CodeRabbit

  • Changed

    • Marked the v1 AsyncClient as deprecated; users are guided to the v2 client.
    • Orderbook queries now accept an optional depth parameter (defaults to 0 if not provided).
  • Bug Fixes

    • Corrected orderbook queries to properly include the depth parameter in v1 AsyncClient.
  • Tests

    • Added tests to verify the deprecation warning for the v1 AsyncClient.
    • Added tests to verify deprecation behavior for an indexer client streaming method.
  • Chores

    • Updated changelog and bumped package version to 1.11.1.

@aarmoa aarmoa requested a review from Copilot August 20, 2025 15:35
Copy link
Contributor

coderabbitai bot commented Aug 20, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds changelog and bumps version to 1.11.1. Deprecates v1 AsyncClient via a DeprecationWarning in its constructor. Four v1 orderbook methods now accept an optional depth param and forward depth (default 0) to indexer calls. Adds unit tests covering AsyncClient and IndexerClient deprecation warnings.

Changes

Cohort / File(s) Summary
Versioning & Changelog
CHANGELOG.md, pyproject.toml
Added 1.11.1 entry; bumped version from 1.11.0 to 1.11.1.
AsyncClient v1: deprecation & depth forwarding
pyinjective/async_client.py
Emits DeprecationWarning in AsyncClient.__init__. Updated signatures of fetch_spot_orderbook_v2, fetch_spot_orderbooks_v2, fetch_derivative_orderbook_v2, fetch_derivative_orderbooks_v2 to accept depth: Optional[int] and forward depth or 0 to indexer client.
Tests: deprecation warnings
tests/test_async_client_deprecation_warnings.py, tests/test_indexer_client_deprecation_warnings.py
Added tests asserting DeprecationWarning when constructing v1 AsyncClient and when calling IndexerClient.listen_derivative_positions_updates, and verifying delegation to underlying indexer stream with expected params.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant AsyncV1 as AsyncClient (v1)
  participant Indexer as IndexerClient

  User->>AsyncV1: __init__(network)
  Note over AsyncV1: emit DeprecationWarning ("Use AsyncClient from async_client_v2")

  User->>AsyncV1: fetch_*_orderbook*_v2(..., depth=None|N)
  AsyncV1->>AsyncV1: depth_to_use = depth or 0
  AsyncV1->>Indexer: fetch_*_orderbook*_v2(..., depth=depth_to_use)
  Indexer-->>AsyncV1: orderbook data
  AsyncV1-->>User: orderbook data
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

A rabbit taps keys with a whisker-thin grin,
“v1 steps aside—let the warnings begin!”
Depth passed along, zero when it's nil,
Tests nod and confirm the old calls still fill.
Hop, bump, release—1.11.1, thrill! 🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/add_depth_to_legacy_async_client_orderbooks_queries

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request fixes the v1 AsyncClient orderbooks queries to include the depth parameter and deprecates the v1 AsyncClient in favor of the v2 version.

Key changes:

  • Added deprecation warning to v1 AsyncClient constructor directing users to v2
  • Enhanced orderbook methods to accept optional depth parameter with default value
  • Added comprehensive test coverage for deprecation warnings

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
pyinjective/async_client.py Added deprecation warning to constructor and depth parameter to orderbook methods
tests/test_async_client_deprecation_warnings.py Added test suite to verify deprecation warning functionality
pyproject.toml Version bump to 1.11.1
CHANGELOG.md Documentation of changes for this release

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

self,
network: Network,
):
warn(
Copy link

Copilot AI Aug 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing import statement for the warn function. The code uses warn() but there's no corresponding import statement visible. This will cause a NameError at runtime.

Copilot uses AI. Check for mistakes.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (3)
CHANGELOG.md (1)

5-11: Changelog accurately reflects the code changes.

Entry clearly calls out the v1 AsyncClient deprecation and the orderbook depth fix. Consider minor polish: wrap AsyncClient and module paths in backticks for readability.

-### Changed
-- Marked the v1 AsyncClient as deprecated
+### Changed
+- Marked the v1 `AsyncClient` as deprecated

-### Fixed
-- Fixed the Indexer orderbooks queries in the v1 AsyncClient to include the depth parameter
+### Fixed
+- Fixed the Indexer orderbooks queries in the v1 `AsyncClient` to include the `depth` parameter
pyinjective/async_client.py (2)

1346-1351: Depth parameter forwarding looks correct; consider lightweight input validation.

Forwarding depth or 0 matches the indexer’s int requirement. Optionally, guard against invalid values (e.g., negatives, non-ints) to fail early with a helpful message.

-    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_orderbook_v2(self, market_id: str, depth: Optional[int] = None) -> Dict[str, Any]:
+        depth_value = 0 if depth is None else depth
+        if not isinstance(depth_value, int) or depth_value < 0:
+            raise ValueError("depth must be a non-negative integer")
+        return await self.indexer_client.fetch_spot_orderbook_v2(market_id=market_id, depth=depth_value)
 
-    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_orderbooks_v2(self, market_ids: List[str], depth: Optional[int] = None) -> Dict[str, Any]:
+        depth_value = 0 if depth is None else depth
+        if not isinstance(depth_value, int) or depth_value < 0:
+            raise ValueError("depth must be a non-negative integer")
+        return await self.indexer_client.fetch_spot_orderbooks_v2(market_ids=market_ids, depth=depth_value)

If you prefer to keep it minimal, add docstrings documenting that depth must be a non-negative integer and that 0 means “default/full depth” (as supported by the Indexer).


1617-1619: Optional: mirror the depth validation done for spot methods.

For consistency and defensive checks, apply the same depth validation here.

-    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_orderbook_v2(self, market_id: str, depth: Optional[int] = None) -> Dict[str, Any]:
+        depth_value = 0 if depth is None else depth
+        if not isinstance(depth_value, int) or depth_value < 0:
+            raise ValueError("depth must be a non-negative integer")
+        return await self.indexer_client.fetch_derivative_orderbook_v2(market_id=market_id, depth=depth_value)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9519524 and a806a5e.

📒 Files selected for processing (4)
  • CHANGELOG.md (1 hunks)
  • pyinjective/async_client.py (3 hunks)
  • pyproject.toml (1 hunks)
  • tests/test_async_client_deprecation_warnings.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
tests/test_async_client_deprecation_warnings.py (2)
pyinjective/core/network.py (3)
  • Network (105-370)
  • create_chain_grpc_channel (353-354)
  • create_chain_stream_grpc_channel (362-363)
pyinjective/async_client.py (1)
  • AsyncClient (56-2481)
pyinjective/async_client.py (1)
pyinjective/indexer_client.py (4)
  • fetch_spot_orderbook_v2 (725-726)
  • fetch_spot_orderbooks_v2 (728-729)
  • fetch_derivative_orderbook_v2 (225-226)
  • fetch_derivative_orderbooks_v2 (228-229)
🪛 LanguageTool
CHANGELOG.md

[grammar] ~5-~5: There might be a mistake here.
Context: ... in this file. ## [1.11.1] - 2025-08-20 ### Changed - Marked the v1 AsyncClient as d...

(QB_NEW_EN)


[grammar] ~6-~6: There might be a mistake here.
Context: ...e. ## [1.11.1] - 2025-08-20 ### Changed - Marked the v1 AsyncClient as deprecated ...

(QB_NEW_EN)


[grammar] ~9-~9: There might be a mistake here.
Context: ... v1 AsyncClient as deprecated ### Fixed - Fixed the Indexer orderbooks queries in ...

(QB_NEW_EN)

🪛 Ruff (0.12.2)
tests/test_async_client_deprecation_warnings.py

4-4: pytest imported but unused

Remove unused import: pytest

(F401)


52-52: Use is and is not for type comparisons, or isinstance() for isinstance checks

(E721)

🪛 GitHub Actions: pre-commit
tests/test_async_client_deprecation_warnings.py

[error] 1-1: pre-commit: trailing-whitespace failed; files were modified by the hook (tests/test_async_client_deprecation_warnings.py).


[warning] 41-41: flakeheaven: pycodestyle: line break after binary operator (W504) [pycodestyle]


[error] 4-4: flakeheaven: pyflakes: 'pytest' imported but unused (F401) [pyflakes]


[error] 1-1: black: reformatted by Black; run 'black --write' to fix code style issues.

pyinjective/async_client.py

[error] 1620-1620: flakeheaven: pycodestyle: line too long (121 > 120 characters) [pycodestyle]


[error] 1-1: black: reformatted by Black; run 'black --write' to fix code style issues.

🔇 Additional comments (2)
pyproject.toml (1)

3-3: Version bump aligned and scoped correctly.

1.11.1 matches the new CHANGELOG entry and the surface-area change is limited to the version field. No concerns.

pyinjective/async_client.py (1)

61-66: Deprecation warning is correctly implemented.

Clear message, correct category, and stacklevel=2 ensures it points to the caller. This aligns with the new deprecation policy.

# 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use identity comparison for classes to address E721.

Compare categories with “is” instead of equality.

-                assert warning.category == DeprecationWarning
+                assert warning.category is DeprecationWarning
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
assert warning.category == DeprecationWarning
assert warning.category is DeprecationWarning
🧰 Tools
🪛 Ruff (0.12.2)

52-52: Use is and is not for type comparisons, or isinstance() for isinstance checks

(E721)

🤖 Prompt for AI Agents
In tests/test_async_client_deprecation_warnings.py around line 52, the test
compares warning.category to DeprecationWarning using == which triggers E721;
change the comparison to use identity (warning.category is DeprecationWarning)
so the class object is compared by identity rather than equality, updating that
assertion accordingly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
tests/test_async_client_deprecation_warnings.py (1)

50-50: Use identity comparison for classes (E721).

Compare the class directly with is to satisfy Ruff/pycodestyle.

-            assert warning.category == DeprecationWarning
+            assert warning.category is DeprecationWarning
🧹 Nitpick comments (1)
tests/test_indexer_client_deprecation_warnings.py (1)

70-70: Use identity comparison for classes (E721).

Match style used elsewhere and satisfy Ruff:

-            assert warning.category == DeprecationWarning
+            assert warning.category is DeprecationWarning
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a806a5e and cc29428.

📒 Files selected for processing (3)
  • pyinjective/async_client.py (3 hunks)
  • tests/test_async_client_deprecation_warnings.py (1 hunks)
  • tests/test_indexer_client_deprecation_warnings.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • pyinjective/async_client.py
🧰 Additional context used
🧬 Code Graph Analysis (2)
tests/test_indexer_client_deprecation_warnings.py (4)
pyinjective/core/network.py (3)
  • Network (105-370)
  • create_exchange_grpc_channel (356-357)
  • create_explorer_grpc_channel (359-360)
pyinjective/indexer_client.py (1)
  • IndexerClient (26-1189)
pyinjective/client/indexer/grpc_stream/indexer_grpc_derivative_stream.py (1)
  • stream_positions (72-88)
pyinjective/async_client.py (1)
  • listen_derivative_positions_updates (1813-1835)
tests/test_async_client_deprecation_warnings.py (2)
pyinjective/core/network.py (3)
  • Network (105-370)
  • create_chain_grpc_channel (353-354)
  • create_chain_stream_grpc_channel (362-363)
pyinjective/async_client.py (1)
  • AsyncClient (56-2483)
🪛 Ruff (0.12.2)
tests/test_indexer_client_deprecation_warnings.py

70-70: Use is and is not for type comparisons, or isinstance() for isinstance checks

(E721)

tests/test_async_client_deprecation_warnings.py

50-50: Use is and is not for type comparisons, or isinstance() for isinstance checks

(E721)

🪛 GitHub Actions: run-tests
tests/test_indexer_client_deprecation_warnings.py

[error] 64-64: Test 'test_listen_derivative_positions_updates_deprecation_warning' failed: expected 1 deprecation warning containing "This method is deprecated. Use listen_derivative_positions_v2_updates instead", but none were emitted. Command: 'poetry run pytest --cov --cov-report=xml -v --full-trace'.

🔇 Additional comments (1)
tests/test_async_client_deprecation_warnings.py (1)

1-58: LGTM: solid deprecation warning coverage and isolation of side effects.

Nice job stubbing network/channel creation and capturing the DeprecationWarning with stacklevel validation. No other issues spotted here.

Comment on lines 37 to 53
# 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"]
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix: await the coroutine so the DeprecationWarning is actually emitted (matches CI failure).

IndexerClient.listen_derivative_positions_updates is async. The test currently calls it without awaiting, so the function body (and warning) never executes, causing the CI failure. Wrap the call in asyncio.run(...) (and make stream_positions an AsyncMock) to execute it.

+import asyncio
-from unittest.mock import MagicMock, patch
+from unittest.mock import MagicMock, patch, AsyncMock
@@
-        client.derivative_stream_api.stream_positions = MagicMock()
+        client.derivative_stream_api.stream_positions = AsyncMock()
@@
-            client.listen_derivative_positions_updates(
-                callback=mock_callback, market_ids=["market_1"], subaccount_ids=["subaccount_1"]
-            )
+            asyncio.run(
+                client.listen_derivative_positions_updates(
+                    callback=mock_callback, market_ids=["market_1"], subaccount_ids=["subaccount_1"]
+                )
+            )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# 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"]
)
import asyncio
from unittest.mock import MagicMock, patch, AsyncMock
# 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 = AsyncMock()
# 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
asyncio.run(
client.listen_derivative_positions_updates(
callback=mock_callback, market_ids=["market_1"], subaccount_ids=["subaccount_1"]
)
)
🤖 Prompt for AI Agents
In tests/test_indexer_client_deprecation_warnings.py around lines 37 to 53, the
test calls the async IndexerClient.listen_derivative_positions_updates without
awaiting so the coroutine body (and its DeprecationWarning) never runs; change
the test to await the coroutine (e.g., wrap the call in asyncio.run(...) or use
the test event loop) and make client.derivative_stream_api.stream_positions an
AsyncMock so the awaited call executes correctly and the warning is emitted and
captured.

Comment on lines 74 to 81
# 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"],
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Assert the awaited call on AsyncMock for accuracy.

Since stream_positions is awaited, assert the awaited call (not just called).

-            client.derivative_stream_api.stream_positions.assert_called_once_with(
+            client.derivative_stream_api.stream_positions.assert_awaited_once_with(
                 callback=mock_callback,
                 on_end_callback=None,
                 on_status_callback=None,
                 market_ids=["market_1"],
                 subaccount_ids=["subaccount_1"],
             )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# 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"],
)
# Verify the underlying method was still called (functionality preserved)
client.derivative_stream_api.stream_positions.assert_awaited_once_with(
callback=mock_callback,
on_end_callback=None,
on_status_callback=None,
market_ids=["market_1"],
subaccount_ids=["subaccount_1"],
)
🤖 Prompt for AI Agents
In tests/test_indexer_client_deprecation_warnings.py around lines 74 to 81, the
test currently uses assert_called_once_with on an AsyncMock for stream_positions
even though the method is awaited; replace the call assertion with the
awaited-call assertion by using the AsyncMock's assert_awaited_once_with and
pass the same keyword args (callback=mock_callback, on_end_callback=None,
on_status_callback=None, market_ids=["market_1"],
subaccount_ids=["subaccount_1"]) so the test verifies the awaited invocation
rather than a plain call.

@aarmoa aarmoa merged commit ac4d044 into master Aug 20, 2025
10 checks passed
@aarmoa aarmoa deleted the fix/add_depth_to_legacy_async_client_orderbooks_queries branch August 20, 2025 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant