Skip to content

Conversation

@aarmoa
Copy link
Collaborator

@aarmoa aarmoa commented May 28, 2025

  • Added support for ERC20 module's queries and messages
  • Added support for EVM module's queries
  • Added unit tests and examples for all new queries and messages

Solves CP-396

Summary by CodeRabbit

  • New Features

    • Added support for ERC20 and EVM queries, including new methods for interacting with ERC20 token pairs and EVM account data.
    • Introduced new example scripts demonstrating how to create, delete, and query ERC20 token pairs, as well as query various EVM-related data.
    • Added new message types for creating and deleting ERC20 token pairs.
  • Bug Fixes

    • Updated derivative market info to include new margin and funding rate fields for improved data accuracy.
  • Documentation

    • Updated changelog to reflect new ERC20 and EVM support and added relevant usage examples.
  • Tests

    • Added comprehensive tests for ERC20 and EVM query APIs and new composer message methods.

@aarmoa aarmoa requested a review from Copilot May 28, 2025 19:45
@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 28, 2025

Walkthrough

This update introduces comprehensive support for ERC20 and EVM proto queries and message types within the client, including new asynchronous API wrappers, message composers, and example scripts. The release also adds corresponding unit tests, updates protobuf descriptors, and modifies some test cases to accommodate new fields and features. Minor version and dependency updates are included.

Changes

File(s) Change Summary
CHANGELOG.md, pyproject.toml, Makefile, buf.gen.yaml Updated changelog, version numbers, and dependency tags.
pyinjective/async_client.py Added async ERC20 and EVM query methods and initialized new API modules in the client.
pyinjective/client/chain/grpc/chain_grpc_erc20_api.py New module: Async gRPC API for ERC20 queries with request handling and authentication.
pyinjective/client/chain/grpc/chain_grpc_evm_api.py New module: Async gRPC API for EVM queries with multiple data fetch methods.
pyinjective/composer.py Added ERC20 message creation methods to Composer for token pair creation and deletion.
pyinjective/proto/exchange/injective_derivative_exchange_rpc_pb2.py Updated protobuf descriptor to include reduce_margin_ratio in DerivativeMarketInfo.
examples/chain_client/erc20/* Added scripts for creating, deleting, and querying ERC20 token pairs.
examples/chain_client/evm/query/* Added scripts for querying EVM accounts, balances, storage, code, and base fee.
examples/chain_client/exchange/28_MsgCreateGTBSpotLimitOrder.py Changed broadcaster instantiation to use gas heuristics.
examples/chain_client/exchange/29_MsgCreateGTBDerivativeLimitOrder.py Changed broadcaster instantiation to use gas heuristics.
tests/client/chain/grpc/configurable_erc20_query_servicer.py New test servicer for configurable ERC20 gRPC responses.
tests/client/chain/grpc/configurable_evm_query_servicer.py New test servicer for configurable EVM gRPC responses.
tests/client/chain/grpc/test_chain_grpc_erc20_api.py New async tests for ERC20 gRPC API client with mock servicer.
tests/client/chain/grpc/test_chain_grpc_evm_api.py New async tests for EVM gRPC API client with mock servicer.
tests/client/indexer/grpc/test_indexer_grpc_derivative_api.py, tests/client/indexer/stream_grpc/* Updated tests to include new fields: reduce_margin_ratio, last_funding_rate.
tests/test_composer.py Added tests for ERC20 message creation in Composer.
tests/test_async_client.py Added Tendermint query mock servicer fixture and integrated it into multiple AsyncClient tests.

Sequence Diagram(s)

sequenceDiagram
    participant UserScript as Example Script
    participant AsyncClient
    participant ChainGrpcERC20Api
    participant ChainGrpcEVMApi
    participant gRPCServer as gRPC Server

    UserScript->>AsyncClient: Call fetch_erc20_all_token_pairs()
    AsyncClient->>ChainGrpcERC20Api: fetch_all_token_pairs()
    ChainGrpcERC20Api->>gRPCServer: QueryAllTokenPairs (gRPC)
    gRPCServer-->>ChainGrpcERC20Api: Response
    ChainGrpcERC20Api-->>AsyncClient: Dict result
    AsyncClient-->>UserScript: Dict result

    UserScript->>AsyncClient: Call fetch_evm_account(address)
    AsyncClient->>ChainGrpcEVMApi: fetch_account(address)
    ChainGrpcEVMApi->>gRPCServer: QueryAccount (gRPC)
    gRPCServer-->>ChainGrpcEVMApi: Response
    ChainGrpcEVMApi-->>AsyncClient: Dict result
    AsyncClient-->>UserScript: Dict result
Loading

Poem

🐇
New fields and APIs, oh what a leap!
ERC20 and EVM, into the code they creep.
Async calls now hop with glee,
Composer crafts new messages, wild and free.
Tests abound, the fields align—
This rabbit says, "The code’s divine!"
🌱


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9ef69b1 and d8112fb.

📒 Files selected for processing (1)
  • tests/test_async_client.py (9 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: run-tests (3.11, windows-latest)
  • GitHub Check: run-tests (3.9, windows-latest)
🔇 Additional comments (7)
tests/test_async_client.py (7)

12-12: LGTM: Import added correctly.

The import for ConfigurableTendermintQueryServicer is properly added and follows the existing import organization pattern.


37-39: LGTM: Fixture follows established pattern.

The tendermint_servicer fixture is implemented consistently with the existing bank_servicer and exchange_servicer fixtures, returning a configurable mock servicer instance.


44-44: LGTM: Test properly integrated with tendermint servicer.

The test method correctly accepts the tendermint_servicer fixture and sets up the mock by assigning it to the client's Tendermint API stub. This enables controlled testing of timeout height synchronization behavior.

Also applies to: 49-49


64-64: LGTM: Account fetching test properly mocked.

The test correctly integrates the tendermint_servicer fixture to control Tendermint queries during account fetching operations, maintaining consistency with the established testing pattern.

Also applies to: 69-69


87-87: LGTM: Market initialization test enhanced with Tendermint mocking.

The comprehensive market initialization test now includes proper Tendermint API mocking alongside existing exchange and bank servicers, ensuring all external dependencies are controlled during testing.

Also applies to: 177-177


214-214: LGTM: Token list reading test properly isolated.

The test for reading tokens from the official list now includes Tendermint servicer mocking, ensuring complete isolation of external dependencies during token and market initialization testing.

Also applies to: 271-271


284-284: LGTM: Chain denom initialization test fully mocked.

The test for initializing tokens from chain denoms now includes all necessary mock servicers (bank, exchange, and tendermint), providing comprehensive isolation for testing the denom metadata retrieval functionality.

Also applies to: 316-316

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
    • Explain this complex logic.
    • 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. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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.

Documentation and Community

  • 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 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

Adds support for Injective v1.16 by integrating new ERC20 and EVM gRPC query APIs, updating client registration, and refreshing examples and dependency versions

  • Introduce ChainGrpcERC20Api and ChainGrpcEVMApi with full set of query methods
  • Register new APIs in AsyncClient and add example scripts for all ERC20 & EVM queries
  • Bump proto versions in buf.gen.yaml, update indexer branch in Makefile, and document changes in CHANGELOG.md

Reviewed Changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated no comments.

Show a summary per file
File Description
pyinjective/client/chain/grpc/chain_grpc_evm_api.py New EVM module query client
pyinjective/client/chain/grpc/chain_grpc_erc20_api.py New ERC20 module query client
pyinjective/async_client.py Registered and exposed ERC20 & EVM APIs in client
examples/chain_client/… Updated examples to use new_using_gas_heuristics and new queries
buf.gen.yaml Bumped Injective proto tags for v1.16
Makefile Updated indexer branch from v1.16.0-rc2 to v1.16.3
CHANGELOG.md Documented added ERC20 and EVM support
Comments suppressed due to low confidence (5)

pyinjective/client/chain/grpc/chain_grpc_evm_api.py:15

  • [nitpick] The method name fetch_params is ambiguous in the EVM context; consider renaming it to fetch_evm_params for consistency with other EVM methods and to parallel the ERC20 client naming.
async def fetch_params(self) -> Dict[str, Any]:

buf.gen.yaml:18

  • Indentation and dash placement were changed on this line, which may break the YAML list structure. Ensure each tag entry retains its leading dash and consistent indentation.
-    tag: v1.0.1-inj

pyinjective/client/chain/grpc/chain_grpc_erc20_api.py:1

  • New ERC20 API methods have been added; verify that corresponding unit tests cover fetch_erc20_params and the other query methods to prevent regressions.
from typing import Any, Callable, Dict

pyinjective/async_client.py:3009

  • The ERC20 Params query is implemented in ChainGrpcERC20Api but not exposed in AsyncClient. Consider adding a fetch_erc20_params wrapper to complete the ERC20 API surface.
async def fetch_erc20_all_token_pairs(self) -> Dict[str, Any]:

pyinjective/async_client.py:3022

  • While most EVM queries are exposed, the EVM Params call (ChainGrpcEVMApi.fetch_params) lacks an AsyncClient wrapper. Add a fetch_evm_params method for full coverage.
async def fetch_evm_account(self, address: str) -> Dict[str, Any]:

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: 18

🧹 Nitpick comments (12)
examples/chain_client/evm/query/1_Account.py (1)

12-35: Add error handling for robustness.

The example demonstrates the EVM account query functionality correctly, but lacks error handling that would make it more robust:

  1. Missing environment variable handling: No check if INJECTIVE_PRIVATE_KEY exists
  2. No network error handling: API calls could fail due to network issues
  3. Hardcoded address: While acceptable for examples, consider adding a comment explaining the address

Consider adding basic error handling:

async def main() -> None:
    dotenv.load_dotenv()
    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
+   
+   if not configured_private_key:
+       raise ValueError("INJECTIVE_PRIVATE_KEY environment variable is required")

    # select network: local, testnet, mainnet
    network = Network.testnet()

    # initialize grpc client
    client = AsyncClient(network)

    # load account
    priv_key = PrivateKey.from_hex(configured_private_key)
    pub_key = priv_key.to_public_key()
    address = pub_key.to_address()
    await client.fetch_account(address.to_acc_bech32())

+   # Example ERC20 contract address on testnet
    erc20_address = "0xDFd5293D8e347dFe59E90eFd55b2956a1343963d"
-   result = await client.fetch_evm_account(address=erc20_address)
-   print(json.dumps(result, indent=2))
+   try:
+       result = await client.fetch_evm_account(address=erc20_address)
+       print(json.dumps(result, indent=2))
+   except Exception as e:
+       print(f"Error fetching EVM account: {e}")
examples/chain_client/evm/query/2_CosmosAccount.py (2)

28-30: Consider making the ERC20 address configurable.

The ERC20 address is hardcoded, which limits the example's flexibility for testing with different contracts.

-    erc20_address = "0xDFd5293D8e347dFe59E90eFd55b2956a1343963d"
+    # You can replace this with any ERC20 contract address you want to query
+    erc20_address = os.getenv("ERC20_ADDRESS", "0xDFd5293D8e347dFe59E90eFd55b2956a1343963d")
     result = await client.fetch_evm_cosmos_account(address=erc20_address)
     print(json.dumps(result, indent=2))

33-34: Consider using asyncio.run() for better compatibility.

The current approach asyncio.get_event_loop().run_until_complete() is deprecated in favor of asyncio.run() in Python 3.7+.

 if __name__ == "__main__":
-    asyncio.get_event_loop().run_until_complete(main())
+    asyncio.run(main())
examples/chain_client/evm/query/4_Balance.py (2)

28-30: Consider making the ERC20 address configurable.

Similar to the previous example, the hardcoded ERC20 address reduces flexibility.

-    erc20_address = "0xDFd5293D8e347dFe59E90eFd55b2956a1343963d"
+    # You can replace this with any ERC20 contract address you want to query
+    erc20_address = os.getenv("ERC20_ADDRESS", "0xDFd5293D8e347dFe59E90eFd55b2956a1343963d")
     result = await client.fetch_evm_balance(address=erc20_address)
     print(json.dumps(result, indent=2))

33-34: Consider using asyncio.run() for better compatibility.

Same modernization opportunity as the previous example.

 if __name__ == "__main__":
-    asyncio.get_event_loop().run_until_complete(main())
+    asyncio.run(main())
examples/chain_client/erc20/2_DeleteTokenPair.py (2)

42-48: Consider parameterizing the hardcoded denomination.

The USDT denomination is hardcoded, which works for demonstration purposes but could be made more flexible for real-world usage.

Consider adding a comment explaining this is a testnet-specific denomination:

+    # Example USDT denomination on testnet - replace with actual denomination for your use case
     usdt_denom = "factory/inj10vkkttgxdeqcgeppu20x9qtyvuaxxev8qh0awq/usdt"

55-58: Verify the necessity of duplicate gas price updates.

The gas price is updated again after broadcasting, but this pattern may not be necessary for single-transaction examples.

Consider whether this gas price refresh is needed for this example, or add a comment explaining why it's included:

+    # Refresh gas price for potential subsequent transactions
     gas_price = await client.current_chain_gas_price()
examples/chain_client/erc20/1_CreateTokenPair.py (1)

57-60: Gas price update pattern is consistent but may be unnecessary.

Same observation as the delete example - the gas price refresh after transaction may not be needed for single-transaction examples.

tests/client/chain/grpc/configurable_evm_query_servicer.py (1)

18-40: Consider adding error handling for empty response queues.

The current implementation will raise an IndexError if a test calls a method when the corresponding response deque is empty. This could lead to unclear test failures.

Consider adding defensive checks or clearer error messages:

 async def Params(self, request: evm_query_pb.QueryParamsRequest, context=None, metadata=None):
+    if not self.params_responses:
+        raise RuntimeError("No more Params responses configured for mock servicer")
     return self.params_responses.pop()

Alternatively, you could return a default empty response or make this behavior configurable based on testing needs.

pyinjective/client/chain/grpc/chain_grpc_evm_api.py (1)

10-65: Consider adding docstrings for better API documentation.

While the code is well-structured and follows established patterns, consider adding docstrings to public methods to improve API documentation and developer experience.

Example for the fetch_account method:

 async def fetch_account(self, address: str) -> Dict[str, Any]:
+    """
+    Fetch EVM account details for the specified address.
+    
+    Args:
+        address: The EVM address to query
+        
+    Returns:
+        Dictionary containing account details
+    """
     request = evm_query_pb.QueryAccountRequest(address=address)
     response = await self._execute_call(call=self._stub.Account, request=request)
     
     return response
pyinjective/async_client.py (2)

3009-3018: Consider adding the missing ERC20 params method.

The ERC20 methods are well-implemented and follow the established delegation pattern. However, the underlying ChainGrpcERC20Api also provides a fetch_erc20_params() method that's not exposed here.

Consider adding the missing method for completeness:

 async def fetch_erc20_token_pair_by_erc20_address(self, erc20_address: str) -> Dict[str, Any]:
     return await self.chain_erc20_api.fetch_token_pair_by_erc20_address(erc20_address=erc20_address)

+async def fetch_erc20_params(self) -> Dict[str, Any]:
+    return await self.chain_erc20_api.fetch_erc20_params()

3022-3042: Consider adding the missing EVM params method.

The EVM methods are well-implemented and provide comprehensive coverage of EVM functionality. However, the underlying ChainGrpcEVMApi also provides a fetch_params() method that's not exposed here.

Consider adding the missing method for completeness:

 async def fetch_evm_base_fee(self) -> Dict[str, Any]:
     return await self.chain_evm_api.fetch_base_fee()

+async def fetch_evm_params(self) -> Dict[str, Any]:
+    return await self.chain_evm_api.fetch_params()
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b8f4603 and cad5bf5.

📒 Files selected for processing (30)
  • CHANGELOG.md (1 hunks)
  • Makefile (1 hunks)
  • buf.gen.yaml (1 hunks)
  • examples/chain_client/erc20/1_CreateTokenPair.py (1 hunks)
  • examples/chain_client/erc20/2_DeleteTokenPair.py (1 hunks)
  • examples/chain_client/erc20/query/1_AllTokenPairs.py (1 hunks)
  • examples/chain_client/erc20/query/2_TokenPairByDenom.py (1 hunks)
  • examples/chain_client/erc20/query/3_TokenPairByERC20Address.py (1 hunks)
  • examples/chain_client/evm/query/1_Account.py (1 hunks)
  • examples/chain_client/evm/query/2_CosmosAccount.py (1 hunks)
  • examples/chain_client/evm/query/3_ValidatorAccount.py (1 hunks)
  • examples/chain_client/evm/query/4_Balance.py (1 hunks)
  • examples/chain_client/evm/query/5_Storage.py (1 hunks)
  • examples/chain_client/evm/query/6_Code.py (1 hunks)
  • examples/chain_client/evm/query/7_BaseFee.py (1 hunks)
  • examples/chain_client/exchange/28_MsgCreateGTBSpotLimitOrder.py (1 hunks)
  • examples/chain_client/exchange/29_MsgCreateGTBDerivativeLimitOrder.py (1 hunks)
  • pyinjective/async_client.py (3 hunks)
  • pyinjective/client/chain/grpc/chain_grpc_erc20_api.py (1 hunks)
  • pyinjective/client/chain/grpc/chain_grpc_evm_api.py (1 hunks)
  • pyinjective/composer.py (2 hunks)
  • pyinjective/proto/exchange/injective_derivative_exchange_rpc_pb2.py (2 hunks)
  • pyproject.toml (1 hunks)
  • tests/client/chain/grpc/configurable_erc20_query_servicer.py (1 hunks)
  • tests/client/chain/grpc/configurable_evm_query_servicer.py (1 hunks)
  • tests/client/chain/grpc/test_chain_grpc_erc20_api.py (1 hunks)
  • tests/client/chain/grpc/test_chain_grpc_evm_api.py (1 hunks)
  • tests/client/indexer/grpc/test_indexer_grpc_derivative_api.py (8 hunks)
  • tests/client/indexer/stream_grpc/test_indexer_grpc_derivative_stream.py (4 hunks)
  • tests/test_composer.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (8)
examples/chain_client/exchange/28_MsgCreateGTBSpotLimitOrder.py (1)
pyinjective/core/broadcaster.py (1)
  • MsgBroadcasterWithPk (62-411)
examples/chain_client/evm/query/1_Account.py (4)
pyinjective/wallet.py (4)
  • PrivateKey (28-103)
  • from_hex (73-76)
  • to_public_key (84-92)
  • to_address (175-181)
pyinjective/async_client.py (3)
  • AsyncClient (74-3293)
  • fetch_account (332-347)
  • fetch_evm_account (3022-3023)
pyinjective/core/network.py (1)
  • testnet (163-215)
pyinjective/client/chain/grpc/chain_grpc_evm_api.py (1)
  • fetch_account (21-25)
examples/chain_client/exchange/29_MsgCreateGTBDerivativeLimitOrder.py (1)
pyinjective/core/broadcaster.py (1)
  • MsgBroadcasterWithPk (62-411)
tests/client/chain/grpc/configurable_evm_query_servicer.py (2)
tests/client/chain/grpc/configurable_erc20_query_servicer.py (1)
  • Params (14-15)
pyinjective/core/network.py (1)
  • metadata (20-25)
pyinjective/client/chain/grpc/chain_grpc_evm_api.py (4)
pyinjective/core/network.py (1)
  • CookieAssistant (11-25)
pyinjective/utils/grpc_api_request_assistant.py (2)
  • GrpcApiRequestAssistant (8-25)
  • execute_call (13-25)
pyinjective/client/chain/grpc/chain_grpc_erc20_api.py (1)
  • _execute_call (39-40)
tests/client/chain/grpc/configurable_evm_query_servicer.py (8)
  • Params (18-19)
  • Account (21-22)
  • CosmosAccount (24-25)
  • ValidatorAccount (27-28)
  • Balance (30-31)
  • Storage (33-34)
  • Code (36-37)
  • BaseFee (39-40)
tests/client/chain/grpc/configurable_erc20_query_servicer.py (1)
tests/client/chain/grpc/configurable_evm_query_servicer.py (1)
  • Params (18-19)
pyinjective/client/chain/grpc/chain_grpc_erc20_api.py (3)
pyinjective/core/network.py (1)
  • CookieAssistant (11-25)
pyinjective/utils/grpc_api_request_assistant.py (2)
  • GrpcApiRequestAssistant (8-25)
  • execute_call (13-25)
tests/client/chain/grpc/configurable_erc20_query_servicer.py (4)
  • Params (14-15)
  • AllTokenPairs (17-18)
  • TokenPairByDenom (20-21)
  • TokenPairByERC20Address (23-26)
pyinjective/async_client.py (2)
pyinjective/client/chain/grpc/chain_grpc_erc20_api.py (4)
  • ChainGrpcERC20Api (10-40)
  • fetch_all_token_pairs (21-25)
  • fetch_token_pair_by_denom (27-31)
  • fetch_token_pair_by_erc20_address (33-37)
pyinjective/client/chain/grpc/chain_grpc_evm_api.py (8)
  • ChainGrpcEVMApi (10-64)
  • fetch_account (21-25)
  • fetch_cosmos_account (27-31)
  • fetch_validator_account (33-37)
  • fetch_balance (39-43)
  • fetch_storage (45-49)
  • fetch_code (51-55)
  • fetch_base_fee (57-61)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: run-tests (3.11, windows-latest)
  • GitHub Check: run-tests (3.10, windows-latest)
🔇 Additional comments (48)
buf.gen.yaml (1)

19-21: LGTM! Version updates align with v1.16 support.

The dependency version bumps for cometbft and cosmos-sdk repositories are appropriate incremental updates that support the new ERC20 and EVM module features being introduced.

pyinjective/proto/exchange/injective_derivative_exchange_rpc_pb2.py (2)

17-17: Generated protobuf code updated correctly.

The serialized descriptor has been updated to include the new reduce_margin_ratio field in the DerivativeMarketInfo message as mentioned in the AI summary.


30-176: Protobuf descriptor offsets updated appropriately.

All the descriptor start/end offsets have been recalculated to accommodate the new field addition. This is the expected behavior when protobuf schemas are regenerated.

pyproject.toml (1)

3-3: Version bump is appropriate for the new features.

The increment from 1.11.0-rc1 to 1.11.0-rc2 correctly reflects the addition of ERC20 and EVM support as documented in the changelog.

CHANGELOG.md (1)

8-12: Changelog accurately documents the new features.

The entries for ERC20 and EVM support are well-formatted and align perfectly with the PR objectives. The documentation of both the core functionality and example additions provides good visibility into the scope of changes.

Makefile (1)

34-34: LGTM! Version update to stable release.

The update from v1.16.0-rc2 to v1.16.3 moves from a release candidate to a stable version, which is appropriate for adding v1.16 support as mentioned in the PR objectives.

examples/chain_client/exchange/28_MsgCreateGTBSpotLimitOrder.py (1)

30-36: LGTM! Valid gas estimation strategy change.

The switch from new_using_simulation to new_using_gas_heuristics is a compatible change that uses message-based gas estimation instead of transaction simulation. Both methods accept identical parameters and provide valid fee calculation strategies.

examples/chain_client/exchange/29_MsgCreateGTBDerivativeLimitOrder.py (1)

30-36: LGTM! Consistent gas estimation strategy update.

This change aligns with the update in 28_MsgCreateGTBSpotLimitOrder.py, providing consistency across exchange examples by standardizing the use of gas heuristics for fee calculation.

examples/chain_client/evm/query/1_Account.py (1)

1-35: Example functionality is correct.

The script properly demonstrates the new EVM account query capability using the fetch_evm_account method. The integration with the pyinjective SDK is correct and follows established patterns from other examples.

examples/chain_client/erc20/query/3_TokenPairByERC20Address.py (1)

28-28: LGTM! Clear example usage with meaningful address.

The hardcoded USDT ERC20 address provides a concrete example that users can understand and test with.

tests/client/indexer/grpc/test_indexer_grpc_derivative_api.py (2)

40-40: LGTM! Consistent addition of lastFundingRate field.

The last_funding_rate field has been correctly added to both the mock PerpetualMarketFunding objects and the corresponding expected results across all relevant test methods.

Also applies to: 118-118, 149-149, 223-223


53-53: LGTM! Consistent addition of reduceMarginRatio field.

The reduce_margin_ratio field has been correctly added to both the mock DerivativeMarketInfo objects and the corresponding expected results across all relevant test methods. This aligns with the protobuf schema updates.

Also applies to: 91-91, 162-162, 196-196

examples/chain_client/evm/query/6_Code.py (1)

28-30: LGTM! Clear demonstration of EVM code querying.

The example correctly demonstrates how to query EVM contract code using the new async client functionality.

examples/chain_client/erc20/query/2_TokenPairByDenom.py (1)

28-29: LGTM! Clear example with appropriate denomination.

The example correctly demonstrates querying ERC20 token pairs by bank denomination using "usdt" as a common and understandable example.

examples/chain_client/evm/query/2_CosmosAccount.py (1)

1-10: LGTM! Clean import structure and good separation of concerns.

The imports are well-organized with standard libraries first, followed by external dependencies, and then pyinjective-specific imports.

examples/chain_client/evm/query/4_Balance.py (1)

1-10: LGTM! Consistent import structure.

The imports follow the same clean pattern as the previous example.

tests/client/indexer/stream_grpc/test_indexer_grpc_derivative_stream.py (4)

45-45: LGTM! Proper addition of new funding rate field.

The last_funding_rate field has been correctly added to the PerpetualMarketFunding mock data with a reasonable test value.


58-58: LGTM! Consistent addition of margin ratio field.

The reduce_margin_ratio field has been properly added to the DerivativeMarketInfo mock data.


108-108: LGTM! Expected output updated to match new schema.

The expected dictionary correctly includes the new reduceMarginRatio field, maintaining consistency with the protobuf schema changes.


135-135: LGTM! Funding rate field properly included in expected output.

The expected dictionary correctly includes the new lastFundingRate field, ensuring the test validates the complete response structure.

pyinjective/composer.py (2)

28-28: LGTM! Clean import for ERC20 protobuf definitions.

The import statement correctly brings in both the ERC20 protobuf definitions (erc20_pb2) and transaction definitions (tx_pb2) from the appropriate module path, following the established naming conventions used throughout the file.


2934-2953: Well-implemented ERC20 token pair management methods.

The new ERC20 module methods are cleanly implemented and follow the established patterns in the codebase:

  • msg_create_token_pair: Properly constructs a TokenPair object and wraps it in a MsgCreateTokenPair message
  • msg_delete_token_pair: Simple and direct implementation for token pair deletion
  • Both methods have appropriate type annotations and parameter naming
  • The code structure follows the regional organization pattern used throughout the class

The implementation correctly uses the imported protobuf classes and maintains consistency with other message construction methods.

examples/chain_client/erc20/2_DeleteTokenPair.py (1)

1-11: LGTM: Clean import structure and dependencies.

The imports are well-organized and follow the established pattern from other example scripts in the codebase.

examples/chain_client/erc20/1_CreateTokenPair.py (1)

42-50: Verify the ERC20 address corresponds to the bank denomination.

The script uses hardcoded values for both the bank denomination and ERC20 address. Ensure these represent the same token on different networks.

The USDT bank denomination and ERC20 address should represent the same underlying asset. Please verify that:

  • factory/inj10vkkttgxdeqcgeppu20x9qtyvuaxxev8qh0awq/usdt corresponds to USDT on Injective
  • 0xdAC17F958D2ee523a2206206994597C13D831ec7 is the correct USDT contract address on Ethereum

Consider adding a comment to clarify this relationship:

+    # USDT token pair: Injective bank denomination and corresponding Ethereum ERC20 address
     usdt_denom = "factory/inj10vkkttgxdeqcgeppu20x9qtyvuaxxev8qh0awq/usdt"
     usdt_erc20 = "0xdAC17F958D2ee523a2206206994597C13D831ec7"
tests/test_composer.py (2)

2177-2196: LGTM: Well-structured test for create token pair message.

The test follows the established pattern and correctly validates the message structure with nested tokenPair object containing bankDenom and erc20Address fields.


2198-2213: LGTM: Consistent test implementation for delete token pair message.

The test correctly validates the simpler structure for delete operations, requiring only sender and bankDenom fields. The implementation is consistent with other composer tests.

tests/client/chain/grpc/configurable_evm_query_servicer.py (1)

6-16: LGTM: Well-organized mock servicer structure.

The class properly inherits from the gRPC QueryServicer and initializes separate deques for each query type, providing good separation of concerns for testing different scenarios.

tests/client/chain/grpc/configurable_erc20_query_servicer.py (1)

1-27: LGTM! Clean test utility implementation.

The configurable servicer follows the established pattern seen in the EVM servicer and provides comprehensive mock support for all ERC20 query methods. The use of deques for pre-configured responses is a solid approach for controlled testing.

tests/client/chain/grpc/test_chain_grpc_evm_api.py (2)

23-108: Excellent comprehensive test coverage for EVM parameters.

The test thoroughly covers all chain configuration parameters and validates the complex nested structure transformation from protobuf to dictionary format. This ensures robust testing of the EVM params functionality.


210-223: Good handling of binary data encoding.

The test correctly handles binary code data by using base64 encoding in the expected response, which matches how the API should transform binary protobuf fields.

tests/client/chain/grpc/test_chain_grpc_erc20_api.py (2)

21-38: Good test coverage for ERC20 parameters.

The test correctly handles the empty params case and validates the response structure transformation.


41-106: Comprehensive token pair testing.

The tests provide excellent coverage of all token pair query methods, validating both the request parameters and response data transformation for different query scenarios.

pyinjective/client/chain/grpc/chain_grpc_erc20_api.py (3)

10-13: Well-structured class initialization.

The constructor properly initializes the gRPC stub and request assistant, following the established pattern used by other gRPC API classes in the codebase.


15-37: Clean and consistent API method implementations.

All four query methods follow a consistent pattern: create request, execute call through the private helper, and return response. This provides good maintainability and follows the DRY principle.


39-40: Good separation of concerns with private helper method.

The _execute_call method centralizes the gRPC call execution and delegates to the request assistant, providing consistent error handling and response processing across all API methods.

pyinjective/client/chain/grpc/chain_grpc_evm_api.py (11)

1-8: LGTM: Clean and appropriate imports.

The imports are well-organized and include all necessary dependencies for the EVM gRPC API implementation.


10-14: LGTM: Consistent constructor implementation.

The constructor follows the established pattern from the ERC20 API, properly initializing the gRPC stub and request assistant with dependency injection.


15-20: LGTM: Clean parameter fetching implementation.

The method correctly creates a parameterless request and delegates to the helper method.


21-26: LGTM: Proper account fetching with address parameter.

The implementation correctly constructs the request with the required address parameter.


27-32: LGTM: Cosmos account query implementation.

The method follows the same reliable pattern as other fetch methods.


33-38: LGTM: Validator account query with consensus address.

The implementation correctly uses the cons_address parameter as expected for validator queries.


39-44: LGTM: Balance query implementation.

The method follows the established pattern for address-based queries.


45-50: LGTM: Storage query with optional key parameter.

The implementation correctly handles the optional key parameter, which will be passed as None to the protobuf request when not provided.


51-56: LGTM: Code fetching implementation.

The method correctly implements contract code retrieval for the specified address.


57-62: LGTM: Base fee query implementation.

The method correctly creates a parameterless request for base fee information.


63-65: LGTM: Consistent helper method implementation.

The private _execute_call method follows the exact same pattern as the ERC20 API, ensuring consistency across the codebase.

pyinjective/async_client.py (2)

13-14: LGTM! Clean import additions.

The new imports for ERC20 and EVM APIs are properly placed and follow the established naming conventions and import structure.


129-136: LGTM! Consistent API initialization.

The ERC20 and EVM API instances are initialized following the same pattern as other chain APIs, with proper dependency injection of the gRPC channel and cookie assistant.

Comment on lines +12 to +33
async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

# select network: local, testnet, mainnet
network = Network.testnet()

# initialize grpc client
client = AsyncClient(network)

# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())

pairs = await client.fetch_erc20_all_token_pairs()
print(json.dumps(pairs, indent=2))


if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
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

Add error handling and use modern asyncio pattern.

The script lacks error handling and uses a deprecated asyncio pattern. Consider these improvements:

  1. Missing error handling: No validation for environment variables or network calls
  2. Deprecated asyncio usage: asyncio.get_event_loop().run_until_complete() is deprecated
  3. Security concern: No validation of private key format
 async def main() -> None:
     dotenv.load_dotenv()
     configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
+    
+    if not configured_private_key:
+        raise ValueError("INJECTIVE_PRIVATE_KEY environment variable is required")

     # select network: local, testnet, mainnet
     network = Network.testnet()

     # initialize grpc client
     client = AsyncClient(network)

-    # load account
-    priv_key = PrivateKey.from_hex(configured_private_key)
-    pub_key = priv_key.to_public_key()
-    address = pub_key.to_address()
-    await client.fetch_account(address.to_acc_bech32())
-
-    pairs = await client.fetch_erc20_all_token_pairs()
-    print(json.dumps(pairs, indent=2))
+    try:
+        # load account
+        priv_key = PrivateKey.from_hex(configured_private_key)
+        pub_key = priv_key.to_public_key()
+        address = pub_key.to_address()
+        await client.fetch_account(address.to_acc_bech32())
+
+        pairs = await client.fetch_erc20_all_token_pairs()
+        print(json.dumps(pairs, indent=2))
+    except Exception as e:
+        print(f"Error: {e}")
+        raise


 if __name__ == "__main__":
-    asyncio.get_event_loop().run_until_complete(main())
+    asyncio.run(main())
📝 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
async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
# select network: local, testnet, mainnet
network = Network.testnet()
# initialize grpc client
client = AsyncClient(network)
# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())
pairs = await client.fetch_erc20_all_token_pairs()
print(json.dumps(pairs, indent=2))
if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
if not configured_private_key:
raise ValueError("INJECTIVE_PRIVATE_KEY environment variable is required")
# select network: local, testnet, mainnet
network = Network.testnet()
# initialize grpc client
client = AsyncClient(network)
try:
# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())
pairs = await client.fetch_erc20_all_token_pairs()
print(json.dumps(pairs, indent=2))
except Exception as e:
print(f"Error: {e}")
raise
if __name__ == "__main__":
asyncio.run(main())
🤖 Prompt for AI Agents
In examples/chain_client/erc20/query/1_AllTokenPairs.py around lines 12 to 33,
add error handling to validate the presence and format of the
INJECTIVE_PRIVATE_KEY environment variable before using it, and wrap network
calls in try-except blocks to catch and handle exceptions gracefully. Replace
the deprecated asyncio.get_event_loop().run_until_complete(main()) with the
modern asyncio.run(main()) pattern for running the async main function.

Comment on lines +12 to +35
async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

# select network: local, testnet, mainnet
network = Network.testnet()

# initialize grpc client
client = AsyncClient(network)

# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())

erc20_address = "0xDFd5293D8e347dFe59E90eFd55b2956a1343963d"
key = "key"
result = await client.fetch_evm_storage(address=erc20_address, key=key)
print(json.dumps(result, indent=2))


if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
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

Apply the same error handling improvements as suggested for the ERC20 example.

This script has identical structural issues to the previous example script.

Apply the same error handling and modern asyncio pattern improvements suggested for the ERC20 token pairs example.

🤖 Prompt for AI Agents
In examples/chain_client/evm/query/5_Storage.py around lines 12 to 35, the
script lacks proper error handling and uses an outdated asyncio pattern.
Refactor the main function to include try-except blocks to catch and log
exceptions during execution. Replace
asyncio.get_event_loop().run_until_complete(main()) with the modern
asyncio.run(main()) for better readability and compatibility.

Comment on lines +28 to +31
erc20_address = "0xDFd5293D8e347dFe59E90eFd55b2956a1343963d"
key = "key"
result = await client.fetch_evm_storage(address=erc20_address, key=key)
print(json.dumps(result, indent=2))
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

Make storage query parameters more meaningful and configurable.

The hardcoded ERC20 address and generic "key" parameter should be more meaningful for a practical example.

-    erc20_address = "0xDFd5293D8e347dFe59E90eFd55b2956a1343963d"
-    key = "key"
+    # Example: Query the balance storage slot for the first account
+    erc20_address = "0xDFd5293D8e347dFe59E90eFd55b2956a1343963d"  # Example USDT contract
+    # Storage key for balance mapping: keccak256(abi.encodePacked(address, slot))
+    # For demonstration, using a meaningful storage key
+    key = "0x0000000000000000000000000000000000000000000000000000000000000000"  # Total supply slot
     result = await client.fetch_evm_storage(address=erc20_address, key=key)
📝 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
erc20_address = "0xDFd5293D8e347dFe59E90eFd55b2956a1343963d"
key = "key"
result = await client.fetch_evm_storage(address=erc20_address, key=key)
print(json.dumps(result, indent=2))
# Example: Query the balance storage slot for the first account
erc20_address = "0xDFd5293D8e347dFe59E90eFd55b2956a1343963d" # Example USDT contract
# Storage key for balance mapping: keccak256(abi.encodePacked(address, slot))
# For demonstration, using a meaningful storage key
key = "0x0000000000000000000000000000000000000000000000000000000000000000" # Total supply slot
result = await client.fetch_evm_storage(address=erc20_address, key=key)
print(json.dumps(result, indent=2))
🤖 Prompt for AI Agents
In examples/chain_client/evm/query/5_Storage.py around lines 28 to 31, the ERC20
address and storage key are hardcoded with generic values that lack practical
meaning. Replace the hardcoded ERC20 address with a relevant, well-known
contract address and update the storage key to a meaningful value that
corresponds to an actual storage slot or variable in that contract.
Additionally, make these parameters configurable, for example by accepting them
as function arguments or reading from a configuration, to allow easier reuse and
testing with different contracts and keys.

Comment on lines +12 to +33
async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

# select network: local, testnet, mainnet
network = Network.testnet()

# initialize grpc client
client = AsyncClient(network)

# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())

result = await client.fetch_evm_base_fee()
print(json.dumps(result, indent=2))


if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
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

Apply consistent error handling and modern asyncio pattern.

This script follows the same pattern as the other examples and should have consistent error handling and use modern asyncio patterns.

Apply the same improvements suggested for the ERC20 token pairs example:

  • Add environment variable validation
  • Add try-catch error handling for network calls
  • Use asyncio.run(main()) instead of the deprecated event loop method
🤖 Prompt for AI Agents
In examples/chain_client/evm/query/7_BaseFee.py from lines 12 to 33, add
validation to check if the environment variable INJECTIVE_PRIVATE_KEY is set and
raise an error or exit if not. Wrap the network calls inside the main async
function with try-except blocks to catch and handle exceptions gracefully.
Replace the deprecated asyncio.get_event_loop().run_until_complete(main()) with
the modern asyncio.run(main()) call in the script entry point for better
compatibility and readability.

Comment on lines +12 to +34
async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

# select network: local, testnet, mainnet
network = Network.testnet()

# initialize grpc client
client = AsyncClient(network)

# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())

cons_address = "injvalcons1h5u937etuat5hnr2s34yaaalfpkkscl5ndadqm"
result = await client.fetch_evm_validator_account(cons_address=cons_address)
print(json.dumps(result, indent=2))


if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
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

Apply consistent error handling improvements.

This script needs the same error handling and asyncio improvements as the other example scripts.

Apply the same error handling, environment variable validation, and modern asyncio pattern improvements suggested for the other example scripts.

🤖 Prompt for AI Agents
In examples/chain_client/evm/query/3_ValidatorAccount.py around lines 12 to 34,
the script lacks proper error handling, environment variable validation, and
uses an outdated asyncio pattern. Add validation to check if the environment
variable INJECTIVE_PRIVATE_KEY is set and raise an error or exit gracefully if
not. Wrap the main async logic in a try-except block to catch and log
exceptions. Replace asyncio.get_event_loop().run_until_complete(main()) with the
modern asyncio.run(main()) call for better compatibility and clarity.

Comment on lines +12 to +26
async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

# select network: local, testnet, mainnet
network = Network.testnet()

# initialize grpc client
client = AsyncClient(network)

# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())
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

Add error handling for missing environment variable.

Same issue as in the Cosmos account example - missing validation for the required environment variable.

 async def main() -> None:
     dotenv.load_dotenv()
     configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
+    
+    if not configured_private_key:
+        raise ValueError("INJECTIVE_PRIVATE_KEY environment variable is required")

     # select network: local, testnet, mainnet
     network = Network.testnet()
📝 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
async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
# select network: local, testnet, mainnet
network = Network.testnet()
# initialize grpc client
client = AsyncClient(network)
# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())
async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
if not configured_private_key:
raise ValueError("INJECTIVE_PRIVATE_KEY environment variable is required")
# select network: local, testnet, mainnet
network = Network.testnet()
# initialize grpc client
client = AsyncClient(network)
# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())
🤖 Prompt for AI Agents
In examples/chain_client/evm/query/4_Balance.py around lines 12 to 26, the code
does not check if the environment variable INJECTIVE_PRIVATE_KEY is set before
using it, which can cause runtime errors. Add a validation step after loading
the environment variable to verify it is not None or empty, and raise a clear
error or exit gracefully if the variable is missing to prevent further failures.

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: 0

🧹 Nitpick comments (1)
tests/client/chain/grpc/test_chain_grpc_erc20_api.py (1)

19-106: Comprehensive test coverage with room for optional improvements.

The test methods provide excellent coverage of all ERC20 API endpoints and correctly verify the protobuf-to-dictionary transformation. Consider these optional improvements for better maintainability:

Optional refactoring suggestions:

  1. Extract test data to constants or fixtures:
+# Test constants
+TEST_BANK_DENOM = "denom"
+TEST_ERC20_ADDRESS = "0xd2C6753F6B1783EF0a3857275e16e79D91b539a3"

+@pytest.fixture
+def sample_token_pair():
+    return erc20_pb.TokenPair(
+        bank_denom=TEST_BANK_DENOM,
+        erc20_address=TEST_ERC20_ADDRESS,
+    )
  1. Consider adding error case tests:
  • Invalid ERC20 address format
  • Non-existent denom/address
  • Network/gRPC errors

This would improve test robustness and catch edge cases in the API layer.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between cad5bf5 and 9ef69b1.

📒 Files selected for processing (2)
  • tests/client/chain/grpc/test_chain_grpc_erc20_api.py (1 hunks)
  • tests/client/chain/grpc/test_chain_grpc_evm_api.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/client/chain/grpc/test_chain_grpc_evm_api.py
🧰 Additional context used
🧬 Code Graph Analysis (1)
tests/client/chain/grpc/test_chain_grpc_erc20_api.py (6)
pyinjective/client/chain/grpc/chain_grpc_erc20_api.py (5)
  • ChainGrpcERC20Api (10-40)
  • fetch_erc20_params (15-19)
  • fetch_all_token_pairs (21-25)
  • fetch_token_pair_by_denom (27-31)
  • fetch_token_pair_by_erc20_address (33-37)
pyinjective/core/network.py (3)
  • DisabledCookieAssistant (97-102)
  • Network (105-370)
  • devnet (145-160)
tests/client/chain/grpc/configurable_erc20_query_servicer.py (2)
  • ConfigurableERC20QueryServicer (6-26)
  • Params (14-15)
tests/client/chain/grpc/test_chain_grpc_evm_api.py (1)
  • _api_instance (242-250)
tests/client/indexer/grpc/test_indexer_grpc_derivative_api.py (1)
  • _api_instance (1382-1390)
tests/client/indexer/stream_grpc/test_indexer_grpc_derivative_stream.py (1)
  • _api_instance (863-871)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: run-tests (3.11, windows-latest)
  • GitHub Check: run-tests (3.10, windows-latest)
🔇 Additional comments (3)
tests/client/chain/grpc/test_chain_grpc_erc20_api.py (3)

1-11: LGTM! Clean and necessary imports.

The import structure is well-organized and includes all the necessary components for testing the ERC20 API functionality.


14-16: LGTM! Simple and effective fixture.

The fixture correctly provides the mock servicer instance needed for all tests.


108-116: LGTM! Consistent test setup pattern.

The helper method follows the established pattern used across other test files in the codebase, ensuring consistency in test infrastructure setup.

@aarmoa aarmoa merged commit aa6bbfb into dev May 29, 2025
13 checks passed
@aarmoa aarmoa deleted the cp-396/add_support_for_v1_16 branch May 29, 2025 02:49
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.

2 participants