Skip to content

Conversation

@aarmoa
Copy link
Collaborator

@aarmoa aarmoa commented Oct 23, 2025

  • Updated proto definitions to injective-core v1.17.0 and indexer v1.17.16

Solves CP-652

Summary by CodeRabbit

  • New Features

    • Chain stream filters for order failures and conditional trigger failures
    • Market open-interest query
    • Open-notional-cap for market launches and updates
    • Offset-position transaction and new rate-limit endpoints
    • New Hyperlane/Warp interchain message and query bindings
  • Deprecations

    • Denom-decimal methods deprecated — use auction-based denom-decimal equivalents
  • Improvements

    • Batch order updates support market-level order creation; expanded examples and tests for new APIs and filters

@aarmoa aarmoa requested a review from Copilot October 23, 2025 12:46
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 23, 2025

Walkthrough

Adds OpenNotionalCap types and plumbing (composer, messages, tests), introduces OffsetPosition RPC and MsgOffsetPosition example, renames denom RPCs/clients to auction-exchange-transfer variants with deprecation shims, adds fetch_open_interest, extends chain stream v2 with order-failure filters, updates Makefile/buf.gen.yaml, and adds many generated Hyperlane and proto/grpc bindings and tests.

Changes

Cohort / File(s) Summary
Build / Tooling
Makefile, buf.gen.yaml
Reduced removals in clean_repos to only injective-indexer; bumped injective-indexer clone tag to v1.17.16 and updated multiple buf.gen.yaml input tags and added hyperlane-cosmos input.
Examples
examples/chain_client/*
Added/updated examples: new 30_MsgOffsetPosition.py; market launch/update examples now pass open_notional_cap (uncapped helper); chain stream example adds order-failure filters; added OpenInterest query example; batch update example extended with market-order creation lists.
Async client & public API
pyinjective/async_client_v2.py
Added fetch_open_interest and auction-exchange-transfer denom methods; fetch_denom_decimal(s) emit DeprecationWarning and delegate; listen_chain_stream_updates accepts and forwards order_failures_filter and conditional_order_trigger_failures_filter.
Composer & message builders
pyinjective/composer_v2.py
Added OpenNotionalCap types and helpers (open_notional_cap, uncapped_open_notional_cap), new msg_offset_position, threaded open_notional_cap through market launch/update builders, extended msg_batch_update_orders to accept spot/derivative/binary market-order creation lists, and added chain-stream failure filter builders.
Client gRPC layers
pyinjective/client/chain/grpc/...
Renamed denom RPCs to AuctionExchangeTransferDenom* variants; added fetch_open_interest wiring; extended chain stream stream_v2 to accept and include order-failure filters in StreamRequest.
Injective proto & generated bindings
pyinjective/proto/injective/**, pyinjective/proto/injective/exchange/**
Added OpenNotionalCap messages and wiring in exchange/market protos; added OffsetPosition RPC and example; removed SetDelegationTransferReceivers; renamed denom fields/requests to auction_exchange_transfer variants; many descriptor range and Params field adjustments.
Hyperlane & other protos
pyinjective/proto/hyperlane/**, pyinjective/proto/exchange/**, pyinjective/proto/injective/peggy/**, pyinjective/proto/injective/stream/v2/**
Added many generated Hyperlane modules (events, query, tx, genesis, types, module, post_dispatch, warp) and corresponding gRPC stubs; Archiver RPC gained StreamSpotAverageEntries; peggy added rate_limit proto and Create/Update/RemoveRateLimit RPCs; stream v2 added order_failures_filter and conditional_order_trigger_failures_filter and new failure update message types.
Tests & mocks
tests/...
Updated servicer mocks to renamed denom RPCs and added OpenInterest responses; added deprecation-warning tests for denom methods; added tests for OffsetPosition, openNotionalCap serialization, stream order-failure updates; updated composer tests and fixtures to use OpenNotionalCap and new serialization helpers.
Changelog
CHANGELOG.md
Added Unreleased block for v1.12.0 noting compiled proto updates for Injective core v1.17.0 and Indexer v1.17.16.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Composer
    participant AsyncClient
    participant ExchangeGRPC

    User->>Composer: composer.uncapped_open_notional_cap()
    Composer-->>User: OpenNotionalCap proto

    User->>Composer: msg_instant_*_market_launch(..., open_notional_cap)
    Composer->>AsyncClient: build Tx including OpenNotionalCap
    AsyncClient->>ExchangeGRPC: Broadcast Msg with open_notional_cap
    ExchangeGRPC-->>AsyncClient: Tx response
    AsyncClient-->>User: Response
Loading
sequenceDiagram
    participant Client
    participant AsyncClient
    participant ExchangeGRPC

    Client->>AsyncClient: fetch_denom_decimal(denom)
    Note right of AsyncClient: emit DeprecationWarning
    AsyncClient->>ExchangeGRPC: AuctionExchangeTransferDenomDecimal(denom)
    ExchangeGRPC-->>AsyncClient: decimal response
    AsyncClient-->>Client: decimal

    Client->>AsyncClient: fetch_open_interest(market_id)
    AsyncClient->>ExchangeGRPC: OpenInterest(market_id)
    ExchangeGRPC-->>AsyncClient: open interest data
    AsyncClient-->>Client: open interest result
Loading
sequenceDiagram
    participant Client
    participant AsyncClient
    participant StreamGRPC

    Client->>AsyncClient: listen_chain_stream_updates(..., order_failures_filter, conditional_order_trigger_failures_filter)
    AsyncClient->>StreamGRPC: StreamV2 request (includes filters)
    StreamGRPC-->>AsyncClient: stream updates (may include OrderFailureUpdate / ConditionalOrderTriggerFailureUpdate)
    AsyncClient-->>Client: forwarded updates
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

  • Areas needing extra attention:
    • Proto/gRPC generated changes (many files): ensure descriptor renames and RPC additions/removals are consistent across stubs, servicers, and client wiring.
    • OpenNotionalCap propagation: serialization/deserialization in composer, gRPC messages, and tests must match proto definitions (capped vs uncapped variants).
    • Deprecation shims: confirm DeprecationWarning behavior and that legacy call-sites still return expected results.
    • Stream v2 filters: verify StreamRequest encoding and downstream handling for order failure filters and new update message types.
    • Makefile/buf.gen.yaml: confirm tag updates and clone targets are correct and intended.

Poem

🐇 I nibble caps and hop through streams bright,

I chase open interest by moonlit byte,
Failed orders now flagged so I sort with a grin,
I offset a position and bound off again,
Protos and stubs sprout wings — a rabbit's delight!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.11% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'CP-652 update protos for v1.17.0 upgrade' clearly summarizes the main change: updating protocol buffer definitions for the v1.17.0 upgrade. It is specific, concise, and directly related to the changeset's primary objective.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cp-652/update_protos_for_v1_17_0

Comment @coderabbitai help to get the list of available commands and usage tips.

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

This PR updates protocol buffer definitions to align with injective-core v1.17.0-beta.3 and indexer v1.17.0-beta, implementing support for new features including open notional caps for markets, chain stream filters for order failures and conditional order trigger failures, and renamed auction exchange transfer denom decimal queries.

Key changes:

  • Added open_notional_cap field to derivative, binary options, and perpetual markets
  • Renamed DenomDecimal/DenomDecimals queries to AuctionExchangeTransferDenomDecimal/AuctionExchangeTransferDenomDecimals
  • Added new chain stream filters for order failures and conditional order trigger failures

Reviewed Changes

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

Show a summary per file
File Description
tests/test_composer_v2.py Added tests for open notional caps and new chain stream filter methods
tests/test_async_client_v2_deprecation_warnings.py Added tests to verify deprecation warnings for renamed denom decimal methods
tests/client/chain/stream_grpc/test_chain_grpc_chain_stream.py Added tests for new order failure and conditional order trigger failure stream updates
tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py Updated tests for renamed denom decimal methods, added seq field to orderbook tests, and added open interest test
tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py Renamed denom decimal response handlers and added open interest response handler
pyinjective/proto/injective/stream/v2/query_pb2.py Updated proto definitions for chain stream with new filter types and response fields
pyinjective/proto/injective/peggy/v1/rate_limit_pb2_grpc.py Added new empty grpc file for rate limit service
pyinjective/proto/injective/peggy/v1/rate_limit_pb2.py Added new proto definitions for peggy rate limiting functionality
pyinjective/proto/injective/peggy/v1/msgs_pb2_grpc.py Added grpc methods for creating, updating, and removing rate limits
pyinjective/proto/injective/peggy/v1/msgs_pb2.py Added proto message definitions for rate limit operations
pyinjective/proto/injective/peggy/v1/genesis_pb2.py Added rate_limits field to genesis state
pyinjective/proto/injective/peggy/v1/events_pb2.py Added EventValidatorJailed event and JailReason enum
pyinjective/proto/injective/exchange/v2/tx_pb2_grpc.py Replaced SetDelegationTransferReceivers with OffsetPosition method
pyinjective/proto/injective/exchange/v2/query_pb2_grpc.py Renamed DenomDecimal/DenomDecimals methods to AuctionExchangeTransferDenomDecimal/AuctionExchangeTransferDenomDecimals, added OpenInterest method
pyinjective/proto/injective/exchange/v2/proposal_pb2.py Renamed UpdateDenomDecimalsProposal to UpdateAuctionExchangeTransferDenomDecimalsProposal, added open_notional_cap to market proposals
pyinjective/proto/injective/exchange/v2/market_pb2.py Added OpenNotionalCap message types and fields to derivative and binary options markets
pyinjective/proto/injective/exchange/v2/genesis_pb2.py Renamed denom_decimals field to auction_exchange_transfer_denom_decimals
pyinjective/proto/injective/exchange/v2/events_pb2.py Added cid field to EventTriggerConditionalMarketOrderFailed and EventTriggerConditionalLimitOrderFailed
pyinjective/proto/injective/exchange/v1beta1/query_pb2_grpc.py Fixed comment for BinaryOptionsMarkets method

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

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/test_composer_v2.py (1)

2128-2152: Duplicate test name shadows an existing test — fix required.
This defines test_msg_privileged_execute_contract a second time; Python will overwrite the earlier function and you’ll silently lose coverage.

Apply one of these:

-def test_msg_privileged_execute_contract(self, basic_composer):
+def test_msg_privileged_execute_contract_alt(self, basic_composer):

or remove the duplicate if redundant.

♻️ Duplicate comments (2)
pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2_grpc.py (1)

1-4: LGTM; same stub-only note as interchain_security events.

Header-only pb2_grpc is fine if no services exist in the proto. See earlier comment for dependency and packaging verification.

pyinjective/proto/hyperlane/core/post_dispatch/v1/types_pb2_grpc.py (1)

1-4: LGTM; matches expected stub for no-service proto.

No additional concerns. Refer to the first pb2_grpc comment for verification steps.

🧹 Nitpick comments (24)
pyinjective/proto/exchange/injective_archiver_rpc_pb2_grpc.py (2)

496-521: EXPERIMENTAL API bridge exposes unary_stream correctly.

Static unary_stream wrapper matches the service path and types. LGTM. As a follow-up, ensure clients set sensible keepalive and backoff for long-lived streams.

  • Consider documenting recommended grpc channel options (keepalive, max_message_length) for this stream in user docs.

149-155: Based on the verification, the extend-per-file-ignores option is valid and allows adding per-file rules on top of existing ones. However, the review comment needs correction regarding the configuration location and syntax.

Correct the Ruff configuration location and syntax.

The review comment suggests the right approach but has formatting issues. Since the repository uses ruff.toml, the correct syntax for ruff.toml is a [per-file-ignores] section with string patterns. The existing [lint.per-file-ignores] section should be extended with:

[lint.per-file-ignores]
"**/__init__.py" = ["E402"]
"**/conftest.py" = ["E402"]
"pyinjective/proto/**/*.py" = ["ARG", "E501"]

Alternatively, use [lint.extend-per-file-ignores] to add these rules without modifying existing entries. The example in the review comment shows valid intent but uses dict-like syntax (appropriate for pyproject.toml), whereas ruff.toml requires table syntax as shown above.

pyinjective/proto/hyperlane/core/v1/events_pb2.py (2)

1-11: Treat generated protos as build artifacts (exclude from lint/typing/coverage).

Avoid CI noise and false positives by excluding pyinjective/proto/** from style/type/coverage checks. No behavior change.

Examples:

  • ruff/flake8: extend-exclude = ["pyinjective/proto/**"]
  • mypy: exclude = '(?x)(^pyinjective/proto/)'
  • coverage (.coveragerc): omit = pyinjective/proto/*

19-19: Document upstream provenance and add regen check in CI.

Add a brief README next to the vendored Hyperlane protos noting upstream repo/commit and license, and add a CI step that re-generates protos and fails on diff to prevent drift.

pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py (1)

60-123: Generated stubs: silence ARG002 without editing generated files.

Ruff ARG002 warnings for unused request/context are expected here. Recommend excluding generated protos from lint (e.g., ruff.toml exclude: ["pyinjective/proto/**"]) rather than touching generated code.

pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2_grpc.py (1)

9-10: Docstring nit: says “Msg service” but this is the Query service.

Harmless, but it can confuse users. If feasible, fix the proto/service comment upstream and re‑generate; otherwise ignore in generated code.

Also applies to: 61-62, 171-174

pyinjective/proto/hyperlane/warp/module/v1/module_pb2.py (1)

4-4: Ensure protobuf/grpc runtime compatibility and dependent pb2 presence.

  • Generated with Protobuf Python Version 5.26.1; pin runtime to >=5.26.1,<6 and ensure grpcio is declared to avoid import/runtime issues.
  • Import depends on pyinjective.proto.cosmos.app.v1alpha1.module_pb2; confirm this file ships in the release.
  • Treat this file as generated-only; don’t hand-edit—regenerate if needed and pin protoc/grpcio-tools versions in your codegen script for reproducibility.

Also applies to: 15-16, 21-25

pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2.py (1)

4-4: Confirm protobuf runtime version.

Header shows “Protobuf Python Version: 5.26.1”. Ensure the project/runtime pins protobuf>=5.26,<6 to avoid incompatibilities with generated code.

pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py (1)

60-119: Silence lint noise for generated stubs (ARG002).

Generated servicer methods intentionally don’t use request yet. Exclude this path from Ruff to avoid churn.

Add to pyproject.toml (or update existing exclude):

 [tool.ruff]
-extend-exclude = []
+extend-exclude = [
+  "pyinjective/proto/**",
+]
examples/chain_client/exchange/query/8_AuctionExchangeTransferDenomDecimal.py (1)

14-16: Rename var for clarity; update print accordingly.

This fetches a single denom’s decimal, not deposits. Rename to avoid confusion.

-    deposits = await client.fetch_auction_exchange_transfer_denom_decimal(
+    denom_decimal = await client.fetch_auction_exchange_transfer_denom_decimal(
         denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"
     )

Also update Line 17 to print(denom_decimal).

examples/chain_client/exchange/query/9_AuctionExchangeTransferDenomDecimals.py (1)

14-16: Align variable name with returned data.

Use a name that reflects decimals list.

-    deposits = await client.fetch_auction_exchange_transfer_denom_decimals(
+    denom_decimals = await client.fetch_auction_exchange_transfer_denom_decimals(
         denoms=["inj", "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"]
     )

Also update Line 17 to print(denom_decimals).

examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py (1)

61-62: Adopts open_notional_cap correctly.

Passing composer.uncapped_open_notional_cap() matches the new v2 surface.

Consider adding a commented example for a capped value for users:

# open_notional_cap=composer.open_notional_cap(Decimal("1_000_000"))
examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py (1)

60-61: Open-notional cap wired into binary options launch.

Looks good and consistent with v2 helpers.

Optionally demonstrate a capped variant alongside uncapped as guidance for integrators.

examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py (1)

61-62: Open-notional cap added to expiry futures launch.

Usage matches v2 API and helper.

Add a brief comment showing capped usage to help users choose between capped/uncapped.

tests/client/chain/stream_grpc/test_chain_grpc_chain_stream.py (1)

629-631: Default “wildcard” filters — consider explicit cases

Using default ["*"] is fine; consider an additional test that passes concrete accounts/subaccounts/markets to validate server-side filter propagation too.

tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (3)

120-128: Silence unused-arg lint and use FIFO pop

Rename unused params and prefer popleft() to model queue semantics.

-    async def AuctionExchangeTransferDenomDecimal(
-        self, request: exchange_query_pb.QueryAuctionExchangeTransferDenomDecimalRequest, context=None, metadata=None
-    ):
-        return self.auction_exchange_transfer_denom_decimal_responses.pop()
+    async def AuctionExchangeTransferDenomDecimal(
+        self, _request: exchange_query_pb.QueryAuctionExchangeTransferDenomDecimalRequest, _context=None, _metadata=None
+    ):
+        return self.auction_exchange_transfer_denom_decimal_responses.popleft()

125-128: Same refinements for plural endpoint

Apply the same underscore-arg and popleft() tweaks here for consistency.

-    async def AuctionExchangeTransferDenomDecimals(
-        self, request: exchange_query_pb.QueryAuctionExchangeTransferDenomDecimalsRequest, context=None, metadata=None
-    ):
-        return self.auction_exchange_transfer_denom_decimals_responses.pop()
+    async def AuctionExchangeTransferDenomDecimals(
+        self, _request: exchange_query_pb.QueryAuctionExchangeTransferDenomDecimalsRequest, _context=None, _metadata=None
+    ):
+        return self.auction_exchange_transfer_denom_decimals_responses.popleft()

394-395: OpenInterest servicer: underscore unused args + FIFO

Mirror the pattern to reduce lints and preserve queue ordering.

-    async def OpenInterest(self, request: exchange_query_pb.QueryOpenInterestRequest, context=None, metadata=None):
-        return self.open_interest_responses.pop()
+    async def OpenInterest(self, _request: exchange_query_pb.QueryOpenInterestRequest, _context=None, _metadata=None):
+        return self.open_interest_responses.popleft()
tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py (2)

1251-1276: Derivative market: OpenNotionalCap (uncapped) — OK; consider capped case

Uncapped path is covered; consider adding a separate test with capped.value to exercise serialization of the capped variant too.

Also applies to: 1342-1344


2398-2422: Binary options market: OpenNotionalCap (uncapped) — OK

Mirrors derivative market coverage; optional follow‑up to add a capped variant test.

Also applies to: 2454-2456

pyinjective/async_client_v2.py (2)

418-430: Deprecation wrappers delegate correctly; add explicit removal version.
Docstrings and warn() messages are fine; consider naming the deprecating version and planned removal version to aid users (e.g., “Deprecated in v1.17; will be removed in v1.18”). No behavior change needed.

Also applies to: 431-443


979-983: New stream filters are correctly threaded through.
Backwards compatible signature extension; consider updating the method docstring to document the two new filters.

Also applies to: 998-1000

tests/test_composer_v2.py (1)

2345-2371: Chain stream filter helpers and defaults — OK. Minor type-hint fix upstream.
Tests validate explicit lists and wildcard defaults. Note: in pyinjective/composer_v2.py the chain_stream_oracle_price_filter function’s return type is annotated as PositionsFilter but returns OraclePriceFilter (per provided snippet). Adjust the annotation to avoid confusion.

Proposed upstream change (pyinjective/composer_v2.py):

-def chain_stream_oracle_price_filter(
-        self,
-        symbols: Optional[List[str]] = None,
-) -> chain_stream_v2_query.PositionsFilter:
+def chain_stream_oracle_price_filter(
+        self,
+        symbols: Optional[List[str]] = None,
+) -> chain_stream_v2_query.OraclePriceFilter:
     symbols = symbols or ["*"]
     return chain_stream_v2_query.OraclePriceFilter(symbol=symbols)

Based on learnings

Also applies to: 2372-2402, 2403-2440, 2441-2476, 2477-2507, 2508-2546, 2547-2574, 2575-2602, 2603-2640

pyinjective/composer_v2.py (1)

1220-1227: Guard against negative caps in open_notional_cap helper.

Add a simple validation to prevent invalid negative values.

 def open_notional_cap(self, value: Decimal) -> injective_market_v2_pb.OpenNotionalCap:
-    chain_value = Token.convert_value_to_extended_decimal_format(value=value)
+    if value < 0:
+        raise ValueError("open_notional_cap value must be non-negative")
+    chain_value = Token.convert_value_to_extended_decimal_format(value=value)
     return injective_market_v2_pb.OpenNotionalCap(
         capped=injective_market_v2_pb.OpenNotionalCapCapped(
             value=f"{chain_value.normalize():f}",
         ),
     )
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 15adf6d and 0a37ea0.

📒 Files selected for processing (88)
  • Makefile (1 hunks)
  • buf.gen.yaml (1 hunks)
  • examples/chain_client/7_ChainStream.py (2 hunks)
  • examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py (1 hunks)
  • examples/chain_client/exchange/25_MsgUpdateDerivativeMarket.py (1 hunks)
  • examples/chain_client/exchange/30_MsgOffsetPosition.py (1 hunks)
  • examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py (1 hunks)
  • examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py (1 hunks)
  • examples/chain_client/exchange/9_MsgBatchUpdateOrders.py (2 hunks)
  • examples/chain_client/exchange/query/66_OpenInterest.py (1 hunks)
  • examples/chain_client/exchange/query/8_AuctionExchangeTransferDenomDecimal.py (1 hunks)
  • examples/chain_client/exchange/query/9_AuctionExchangeTransferDenomDecimals.py (1 hunks)
  • pyinjective/async_client_v2.py (5 hunks)
  • pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (2 hunks)
  • pyinjective/client/chain/grpc_stream/chain_grpc_chain_stream.py (2 hunks)
  • pyinjective/composer_v2.py (13 hunks)
  • pyinjective/proto/exchange/injective_archiver_rpc_pb2.py (2 hunks)
  • pyinjective/proto/exchange/injective_archiver_rpc_pb2_grpc.py (4 hunks)
  • pyinjective/proto/exchange/injective_auction_rpc_pb2.py (2 hunks)
  • pyinjective/proto/exchange/injective_megavault_rpc_pb2.py (2 hunks)
  • pyinjective/proto/google/longrunning/operations_pb2.py (2 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/events_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/events_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/genesis_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/genesis_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/types_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/types_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/module/v1/module_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/module/v1/module_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/events_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/events_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/types_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/types_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/events_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/events_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/genesis_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/genesis_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/query_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/tx_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/types_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/types_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/module/v1/module_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/module/v1/module_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/events_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/events_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/genesis_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/genesis_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/query_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/tx_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/tx_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/types_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/types_pb2_grpc.py (1 hunks)
  • pyinjective/proto/injective/exchange/v1beta1/exchange_pb2.py (4 hunks)
  • pyinjective/proto/injective/exchange/v1beta1/query_pb2_grpc.py (1 hunks)
  • pyinjective/proto/injective/exchange/v1beta1/tx_pb2.py (4 hunks)
  • pyinjective/proto/injective/exchange/v1beta1/tx_pb2_grpc.py (0 hunks)
  • pyinjective/proto/injective/exchange/v2/events_pb2.py (2 hunks)
  • pyinjective/proto/injective/exchange/v2/exchange_pb2.py (2 hunks)
  • pyinjective/proto/injective/exchange/v2/genesis_pb2.py (3 hunks)
  • pyinjective/proto/injective/exchange/v2/market_pb2.py (4 hunks)
  • pyinjective/proto/injective/exchange/v2/proposal_pb2.py (7 hunks)
  • pyinjective/proto/injective/exchange/v2/query_pb2_grpc.py (12 hunks)
  • pyinjective/proto/injective/exchange/v2/tx_pb2_grpc.py (4 hunks)
  • pyinjective/proto/injective/peggy/v1/events_pb2.py (3 hunks)
  • pyinjective/proto/injective/peggy/v1/genesis_pb2.py (2 hunks)
  • pyinjective/proto/injective/peggy/v1/msgs_pb2.py (3 hunks)
  • pyinjective/proto/injective/peggy/v1/msgs_pb2_grpc.py (4 hunks)
  • pyinjective/proto/injective/peggy/v1/rate_limit_pb2.py (1 hunks)
  • pyinjective/proto/injective/peggy/v1/rate_limit_pb2_grpc.py (1 hunks)
  • pyinjective/proto/injective/stream/v2/query_pb2.py (3 hunks)
  • tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (4 hunks)
  • tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py (18 hunks)
  • tests/client/chain/stream_grpc/test_chain_grpc_chain_stream.py (5 hunks)
  • tests/test_async_client_v2_deprecation_warnings.py (1 hunks)
  • tests/test_composer_v2.py (18 hunks)
💤 Files with no reviewable changes (1)
  • pyinjective/proto/injective/exchange/v1beta1/tx_pb2_grpc.py
🧰 Additional context used
🧬 Code graph analysis (26)
pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py (1)
pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py (4)
  • MsgStub (8-57)
  • MsgServicer (60-118)
  • add_MsgServicer_to_server (121-167)
  • Msg (171-389)
examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py (3)
pyinjective/composer_v2.py (2)
  • open_notional_cap (1220-1226)
  • uncapped_open_notional_cap (1228-1229)
pyinjective/async_client_v2.py (1)
  • composer (1267-1270)
pyinjective/async_client.py (1)
  • composer (2222-2229)
examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py (2)
pyinjective/composer_v2.py (2)
  • open_notional_cap (1220-1226)
  • uncapped_open_notional_cap (1228-1229)
pyinjective/async_client_v2.py (1)
  • composer (1267-1270)
examples/chain_client/exchange/query/8_AuctionExchangeTransferDenomDecimal.py (2)
pyinjective/async_client_v2.py (1)
  • fetch_auction_exchange_transfer_denom_decimal (444-445)
pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (1)
  • fetch_auction_exchange_transfer_denom_decimal (90-94)
examples/chain_client/exchange/30_MsgOffsetPosition.py (5)
pyinjective/async_client_v2.py (5)
  • AsyncClient (54-1524)
  • initialize_tokens_from_chain_denoms (1286-1329)
  • composer (1267-1270)
  • current_chain_gas_price (1272-1284)
  • fetch_account (228-243)
pyinjective/core/broadcaster.py (1)
  • new_using_simulation (82-113)
pyinjective/core/network.py (2)
  • Network (105-378)
  • testnet (165-219)
pyinjective/wallet.py (5)
  • PrivateKey (28-103)
  • from_hex (73-76)
  • to_public_key (84-92)
  • to_address (175-181)
  • get_subaccount_id (263-266)
pyinjective/composer_v2.py (1)
  • msg_offset_position (1210-1218)
pyinjective/proto/injective/exchange/v2/query_pb2_grpc.py (1)
tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (3)
  • AuctionExchangeTransferDenomDecimal (120-123)
  • AuctionExchangeTransferDenomDecimals (125-128)
  • OpenInterest (394-395)
tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (1)
pyinjective/proto/injective/exchange/v2/query_pb2_grpc.py (6)
  • AuctionExchangeTransferDenomDecimal (432-437)
  • AuctionExchangeTransferDenomDecimal (1468-1492)
  • AuctionExchangeTransferDenomDecimals (439-445)
  • AuctionExchangeTransferDenomDecimals (1495-1519)
  • OpenInterest (835-840)
  • OpenInterest (3007-3031)
examples/chain_client/exchange/query/9_AuctionExchangeTransferDenomDecimals.py (2)
pyinjective/async_client_v2.py (1)
  • fetch_auction_exchange_transfer_denom_decimals (447-450)
pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (1)
  • fetch_auction_exchange_transfer_denom_decimals (96-102)
examples/chain_client/exchange/9_MsgBatchUpdateOrders.py (2)
pyinjective/async_client_v2.py (1)
  • composer (1267-1270)
pyinjective/composer_v2.py (4)
  • derivative_order (403-427)
  • calculate_margin (393-401)
  • spot_order (360-391)
  • msg_batch_update_orders (757-789)
examples/chain_client/7_ChainStream.py (2)
pyinjective/async_client_v2.py (1)
  • composer (1267-1270)
pyinjective/composer_v2.py (2)
  • chain_stream_order_failures_filter (1586-1591)
  • chain_stream_conditional_order_trigger_failures_filter (1593-1602)
examples/chain_client/exchange/query/66_OpenInterest.py (3)
pyinjective/async_client_v2.py (1)
  • fetch_open_interest (845-846)
pyinjective/core/network.py (1)
  • testnet (165-219)
pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (1)
  • fetch_open_interest (656-660)
pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py (1)
pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py (4)
  • QueryStub (8-57)
  • QueryServicer (60-122)
  • add_QueryServicer_to_server (125-171)
  • Query (175-393)
examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py (2)
pyinjective/composer_v2.py (2)
  • open_notional_cap (1220-1226)
  • uncapped_open_notional_cap (1228-1229)
pyinjective/async_client_v2.py (1)
  • composer (1267-1270)
pyinjective/async_client_v2.py (1)
pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (3)
  • fetch_auction_exchange_transfer_denom_decimal (90-94)
  • fetch_auction_exchange_transfer_denom_decimals (96-102)
  • fetch_open_interest (656-660)
pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py (3)
pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py (4)
  • QueryStub (8-37)
  • QueryServicer (40-70)
  • add_QueryServicer_to_server (73-99)
  • Query (103-213)
pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2_grpc.py (4)
  • QueryStub (8-57)
  • QueryServicer (60-118)
  • add_QueryServicer_to_server (121-167)
  • Query (171-389)
pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py (4)
  • QueryStub (8-42)
  • QueryServicer (45-82)
  • add_QueryServicer_to_server (85-116)
  • Query (120-257)
pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (4)
pyinjective/async_client_v2.py (3)
  • fetch_auction_exchange_transfer_denom_decimal (444-445)
  • fetch_auction_exchange_transfer_denom_decimals (447-450)
  • fetch_open_interest (845-846)
pyinjective/client/chain/grpc/chain_grpc_exchange_api.py (1)
  • _execute_call (638-639)
tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (3)
  • AuctionExchangeTransferDenomDecimal (120-123)
  • AuctionExchangeTransferDenomDecimals (125-128)
  • OpenInterest (394-395)
pyinjective/proto/injective/exchange/v2/query_pb2_grpc.py (6)
  • AuctionExchangeTransferDenomDecimal (432-437)
  • AuctionExchangeTransferDenomDecimal (1468-1492)
  • AuctionExchangeTransferDenomDecimals (439-445)
  • AuctionExchangeTransferDenomDecimals (1495-1519)
  • OpenInterest (835-840)
  • OpenInterest (3007-3031)
pyinjective/composer_v2.py (1)
pyinjective/core/token.py (1)
  • convert_value_to_extended_decimal_format (19-20)
pyinjective/proto/hyperlane/warp/v1/tx_pb2_grpc.py (1)
pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py (4)
  • MsgStub (8-32)
  • MsgServicer (35-58)
  • add_MsgServicer_to_server (61-82)
  • Msg (86-169)
examples/chain_client/exchange/25_MsgUpdateDerivativeMarket.py (2)
pyinjective/async_client_v2.py (1)
  • composer (1267-1270)
pyinjective/composer_v2.py (1)
  • uncapped_open_notional_cap (1228-1229)
tests/test_async_client_v2_deprecation_warnings.py (3)
pyinjective/async_client_v2.py (2)
  • fetch_denom_decimal (418-429)
  • fetch_denom_decimals (431-442)
pyinjective/core/network.py (1)
  • local (266-283)
tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (1)
  • ConfigurableExchangeV2QueryServicer (9-395)
tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py (3)
pyinjective/async_client_v2.py (3)
  • fetch_auction_exchange_transfer_denom_decimal (444-445)
  • fetch_auction_exchange_transfer_denom_decimals (447-450)
  • fetch_open_interest (845-846)
pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (3)
  • fetch_auction_exchange_transfer_denom_decimal (90-94)
  • fetch_auction_exchange_transfer_denom_decimals (96-102)
  • fetch_open_interest (656-660)
tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (1)
  • OpenInterest (394-395)
tests/client/chain/stream_grpc/test_chain_grpc_chain_stream.py (1)
pyinjective/composer_v2.py (2)
  • chain_stream_order_failures_filter (1586-1591)
  • chain_stream_conditional_order_trigger_failures_filter (1593-1602)
pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py (2)
pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2_grpc.py (4)
  • MsgStub (8-52)
  • MsgServicer (55-106)
  • add_MsgServicer_to_server (109-150)
  • Msg (154-345)
pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py (4)
  • MsgStub (8-32)
  • MsgServicer (35-58)
  • add_MsgServicer_to_server (61-82)
  • Msg (86-169)
tests/test_composer_v2.py (2)
pyinjective/composer_v2.py (14)
  • open_notional_cap (1220-1226)
  • spot_order (360-391)
  • derivative_order (403-427)
  • binary_options_order (429-453)
  • uncapped_open_notional_cap (1228-1229)
  • chain_stream_bank_balances_filter (1532-1536)
  • chain_stream_subaccount_deposits_filter (1538-1543)
  • chain_stream_trades_filter (1545-1552)
  • chain_stream_orders_filter (1554-1561)
  • chain_stream_orderbooks_filter (1563-1568)
  • chain_stream_positions_filter (1570-1577)
  • chain_stream_oracle_price_filter (1579-1584)
  • chain_stream_order_failures_filter (1586-1591)
  • chain_stream_conditional_order_trigger_failures_filter (1593-1602)
pyinjective/core/token.py (1)
  • convert_value_to_extended_decimal_format (19-20)
pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2_grpc.py (2)
pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py (4)
  • MsgStub (8-57)
  • MsgServicer (60-118)
  • add_MsgServicer_to_server (121-167)
  • Msg (171-389)
pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py (4)
  • MsgStub (8-32)
  • MsgServicer (35-58)
  • add_MsgServicer_to_server (61-82)
  • Msg (86-169)
pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2_grpc.py (2)
pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py (4)
  • QueryStub (8-57)
  • QueryServicer (60-122)
  • add_QueryServicer_to_server (125-171)
  • Query (175-393)
pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py (4)
  • QueryStub (8-42)
  • QueryServicer (45-82)
  • add_QueryServicer_to_server (85-116)
  • Query (120-257)
🪛 Gitleaks (8.28.0)
tests/test_composer_v2.py

[high] 2345-2345: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 2576-2576: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 Ruff (0.14.1)
pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py

39-39: Unused method argument: request

(ARG002)


46-46: Unused method argument: request

(ARG002)


53-53: Unused method argument: request

(ARG002)

pyinjective/proto/exchange/injective_archiver_rpc_pb2_grpc.py

149-149: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py

44-44: Unused method argument: request

(ARG002)


51-51: Unused method argument: request

(ARG002)


58-58: Unused method argument: request

(ARG002)


65-65: Unused method argument: request

(ARG002)

pyinjective/proto/injective/exchange/v2/query_pb2_grpc.py

432-432: Unused method argument: request

(ARG002)


439-439: Unused method argument: request

(ARG002)


835-835: Unused method argument: request

(ARG002)

tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py

121-121: Unused method argument: request

(ARG002)


121-121: Unused method argument: context

(ARG002)


121-121: Unused method argument: metadata

(ARG002)


126-126: Unused method argument: request

(ARG002)


126-126: Unused method argument: context

(ARG002)


126-126: Unused method argument: metadata

(ARG002)


394-394: Unused method argument: request

(ARG002)


394-394: Unused method argument: context

(ARG002)


394-394: Unused method argument: metadata

(ARG002)

examples/chain_client/exchange/9_MsgBatchUpdateOrders.py

113-113: Decimal() called with float literal argument

Replace with string literal

(RUF032)


115-115: Decimal() called with float literal argument

Replace with string literal

(RUF032)

pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py

49-49: Unused method argument: request

(ARG002)


56-56: Unused method argument: request

(ARG002)


63-63: Unused method argument: request

(ARG002)


70-70: Unused method argument: request

(ARG002)


77-77: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py

64-64: Unused method argument: request

(ARG002)


71-71: Unused method argument: request

(ARG002)


78-78: Unused method argument: request

(ARG002)


85-85: Unused method argument: request

(ARG002)


96-96: Unused method argument: request

(ARG002)


103-103: Unused method argument: request

(ARG002)


110-110: Unused method argument: request

(ARG002)


117-117: Unused method argument: request

(ARG002)

pyinjective/proto/injective/exchange/v2/tx_pb2_grpc.py

490-490: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/warp/v1/tx_pb2_grpc.py

59-59: Unused method argument: request

(ARG002)


66-66: Unused method argument: request

(ARG002)


73-73: Unused method argument: request

(ARG002)


80-80: Unused method argument: request

(ARG002)


87-87: Unused method argument: request

(ARG002)


94-94: Unused method argument: request

(ARG002)


101-101: Unused method argument: request

(ARG002)

pyinjective/proto/injective/peggy/v1/msgs_pb2_grpc.py

194-194: Unused method argument: request

(ARG002)


202-202: Unused method argument: request

(ARG002)


210-210: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py

64-64: Unused method argument: request

(ARG002)


71-71: Unused method argument: request

(ARG002)


78-78: Unused method argument: request

(ARG002)


85-85: Unused method argument: request

(ARG002)


92-92: Unused method argument: request

(ARG002)


99-99: Unused method argument: request

(ARG002)


106-106: Unused method argument: request

(ARG002)


113-113: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2_grpc.py

59-59: Unused method argument: request

(ARG002)


66-66: Unused method argument: request

(ARG002)


73-73: Unused method argument: request

(ARG002)


80-80: Unused method argument: request

(ARG002)


87-87: Unused method argument: request

(ARG002)


94-94: Unused method argument: request

(ARG002)


101-101: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2_grpc.py

64-64: Unused method argument: request

(ARG002)


71-71: Unused method argument: request

(ARG002)


78-78: Unused method argument: request

(ARG002)


85-85: Unused method argument: request

(ARG002)


92-92: Unused method argument: request

(ARG002)


99-99: Unused method argument: request

(ARG002)


106-106: Unused method argument: request

(ARG002)


113-113: Unused method argument: request

(ARG002)

Comment on lines +1 to +68
import asyncio
import json
import os

import dotenv

from pyinjective.async_client_v2 import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


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)
await client.initialize_tokens_from_chain_denoms()
composer = await client.composer()

gas_price = await client.current_chain_gas_price()
# adjust gas price to make it valid even if it changes between the time it is requested and the TX is broadcasted
gas_price = int(gas_price * 1.1)

message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
network=network,
private_key=configured_private_key,
gas_price=gas_price,
client=client,
composer=composer,
)

# 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())

offsetting_subaccount_ids = {
"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
}

# prepare tx msg
message = composer.msg_offset_position(
sender=address.to_acc_bech32(),
subaccount_id=address.get_subaccount_id(index=0),
market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
offsetting_subaccount_ids=offsetting_subaccount_ids,
)

# broadcast the transaction
result = await message_broadcaster.broadcast([message])
print("---Transaction Response---")
print(json.dumps(result, indent=2))

gas_price = await client.current_chain_gas_price()
# adjust gas price to make it valid even if it changes between the time it is requested and the TX is broadcasted
gas_price = int(gas_price * 1.1)
message_broadcaster.update_gas_price(gas_price=gas_price)


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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Prevent runtime errors; use list for repeated field; round gas price up.

  • Validate INJECTIVE_PRIVATE_KEY before use.
  • Pass a list (not a set) for offsetting_subaccount_ids to preserve order and match type hints.
  • Use ceil when bumping gas price to avoid rounding down.
  • Prefer asyncio.run for simplicity.
@@
-import asyncio
+import asyncio
+import math
 import json
 import os
@@
     dotenv.load_dotenv()
-    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
+    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
+    if not configured_private_key:
+        raise ValueError("INJECTIVE_PRIVATE_KEY env var is required for this example.")
@@
-    gas_price = int(gas_price * 1.1)
+    gas_price = math.ceil(gas_price * 1.1)
@@
-    offsetting_subaccount_ids = {
+    offsetting_subaccount_ids = [
         "0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
-    }
+    ]
@@
-    gas_price = int(gas_price * 1.1)
+    gas_price = math.ceil(gas_price * 1.1)
@@
-if __name__ == "__main__":
-    asyncio.get_event_loop().run_until_complete(main())
+if __name__ == "__main__":
+    asyncio.run(main())

Optional: document python-dotenv as a requirement for running examples.



---

🏁 Script executed:

```shell
#!/bin/bash
# Find the file and verify it exists
fd -t f "30_MsgOffsetPosition.py"

Length of output: 54


🏁 Script executed:

#!/bin/bash
# Search for msg_offset_position method definition to check parameter types
rg -n "def msg_offset_position" -A 10 --type=py

Length of output: 866


🏁 Script executed:

#!/bin/bash
# Check env var validation patterns in other examples
rg -n "getenv\(" examples/ -B 2 -A 2 --type=py | head -60

Length of output: 4230


🏁 Script executed:

#!/bin/bash
# Look for requirements or setup files documenting python-dotenv
fd -t f -E "*.pyc" "\.(txt|cfg|toml|yaml|yml)$" | xargs rg -l "python-dotenv|dotenv" 2>/dev/null | head -20

Length of output: 14


🏁 Script executed:

#!/bin/bash
# Check other examples for gas price calculation patterns
rg -n "gas_price.*\*|math\.ceil" examples/ -B 2 -A 2 --type=py | head -80

Length of output: 7566


🏁 Script executed:

#!/bin/bash
# Check for asyncio patterns - asyncio.run vs get_event_loop
rg -n "asyncio\.(run|get_event_loop)" examples/ --type=py

Length of output: 39792


Fix set-to-list conversion for repeated field; validate env var to prevent crashes.

The code passes a set for offsetting_subaccount_ids, but the composer method signature requires List[str]. This type mismatch will cause runtime errors. Additionally, missing INJECTIVE_PRIVATE_KEY environment variable will crash without validation.

  • Convert offsetting_subaccount_ids from set {...} to list [...].
  • Validate INJECTIVE_PRIVATE_KEY is not None before use.

Optional improvements noted in original review (gas price rounding, asyncio.run) diverge from current codebase patterns but are reasonable modernizations for consistency across future examples.

@@
+import math
 import os
 import dotenv
@@
-    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
+    configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
+    if not configured_private_key:
+        raise ValueError("INJECTIVE_PRIVATE_KEY env var is required for this example.")
@@
-    offsetting_subaccount_ids = {
+    offsetting_subaccount_ids = [
         "0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
         "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
-    }
+    ]
🤖 Prompt for AI Agents
In examples/chain_client/exchange/30_MsgOffsetPosition.py around lines 1 to 68,
the example constructs offsetting_subaccount_ids as a Python set and passes it
to composer.msg_offset_position which expects a List[str], and it uses
INJECTIVE_PRIVATE_KEY without validating it; change the
offsetting_subaccount_ids to a list literal (square brackets) so the repeated
field receives a list of strings, and add a guard after reading
INJECTIVE_PRIVATE_KEY to check it is not None/empty and exit or raise a clear
error if missing before using it.

Comment on lines +113 to +116
quantity=Decimal(0.1),
margin=composer.calculate_margin(
quantity=Decimal(0.1), price=Decimal(25100), leverage=Decimal(1), is_reduce_only=False
),
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 | 🟡 Minor

Avoid Decimal(float); use string literal to prevent FP rounding (RUF032).

-            quantity=Decimal(0.1),
+            quantity=Decimal("0.1"),
@@
-                quantity=Decimal(0.1), price=Decimal(25100), leverage=Decimal(1), is_reduce_only=False
+                quantity=Decimal("0.1"), price=Decimal(25100), leverage=Decimal(1), is_reduce_only=False
📝 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
quantity=Decimal(0.1),
margin=composer.calculate_margin(
quantity=Decimal(0.1), price=Decimal(25100), leverage=Decimal(1), is_reduce_only=False
),
quantity=Decimal("0.1"),
margin=composer.calculate_margin(
quantity=Decimal("0.1"), price=Decimal(25100), leverage=Decimal(1), is_reduce_only=False
),
🧰 Tools
🪛 Ruff (0.14.1)

113-113: Decimal() called with float literal argument

Replace with string literal

(RUF032)


115-115: Decimal() called with float literal argument

Replace with string literal

(RUF032)

🤖 Prompt for AI Agents
In examples/chain_client/exchange/9_MsgBatchUpdateOrders.py around lines 113 to
116, Decimal is being constructed from a float (Decimal(0.1)), which can
introduce FP rounding; replace Decimal(0.1) with a string literal like
Decimal("0.1") (and similarly use Decimal("1") if you want to construct from a
numeric literal consistently) and ensure any Decimal created from non-integer
values uses string literals instead of float arguments.

Comment on lines +9 to +11
"""
Demonstrate fetching denom min notionals using AsyncClient.
"""
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 | 🟡 Minor

Fix example docstring to match behavior.

-    """
-    Demonstrate fetching denom min notionals using AsyncClient.
-    """
+    """
+    Demonstrate fetching open interest using AsyncClient.
+    """
📝 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
"""
Demonstrate fetching denom min notionals using AsyncClient.
"""
"""
Demonstrate fetching open interest using AsyncClient.
"""
🤖 Prompt for AI Agents
In examples/chain_client/exchange/query/66_OpenInterest.py around lines 9-11,
the module docstring currently says "Demonstrate fetching denom min notionals
using AsyncClient" which doesn't match the file's purpose; update the docstring
to accurately describe the script (e.g., "Demonstrate fetching open interest
using AsyncClient" or similar), ensure it references AsyncClient only if the
code is asynchronous, and keep it brief and aligned with the implemented
behavior.

Comment on lines +1210 to +1218
def msg_offset_position(
self, sender: str, subaccount_id: str, market_id: str, offsetting_subaccount_ids: List[str]
) -> injective_exchange_tx_v2_pb.MsgOffsetPosition:
return injective_exchange_tx_v2_pb.MsgOffsetPosition(
sender=sender,
subaccount_id=subaccount_id,
market_id=market_id,
offsetting_subaccount_ids=offsetting_subaccount_ids,
)
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 | 🔴 Critical

🧩 Analysis chain

Missing message/response map entries for MsgOffsetPosition will break unpack helpers.

Composer exposes msg_offset_position, but GRPC maps (REQUEST_TO_RESPONSE_TYPE_MAP, GRPC_MESSAGE_TYPE_TO_CLASS_MAP, GRPC_RESPONSE_TYPE_TO_CLASS_MAP) lack entries for MsgOffsetPosition/Response. UnpackMsgExecResponse/UnpackTransactionMessages will KeyError for these.

Apply this diff to register the message and its response:

--- a/pyinjective/composer_v2.py
+++ b/pyinjective/composer_v2.py
@@ -90,6 +90,8 @@ REQUEST_TO_RESPONSE_TYPE_MAP = {
     "MsgInstantBinaryOptionsMarketLaunch":
         injective_exchange_tx_v2_pb.MsgInstantBinaryOptionsMarketLaunchResponse,
+    "MsgOffsetPosition":
+        injective_exchange_tx_v2_pb.MsgOffsetPositionResponse,
 }
@@ -192,6 +194,8 @@ GRPC_MESSAGE_TYPE_TO_CLASS_MAP = {
     "/injective.exchange.v2.MsgInstantBinaryOptionsMarketLaunch":
         injective_exchange_tx_v2_pb.MsgInstantBinaryOptionsMarketLaunch,
+    "/injective.exchange.v2.MsgOffsetPosition":
+        injective_exchange_tx_v2_pb.MsgOffsetPosition,
 }
@@ -293,6 +297,8 @@ GRPC_RESPONSE_TYPE_TO_CLASS_MAP = {
     "/injective.exchange.v2.MsgInstantBinaryOptionsMarketLaunchResponse":
         injective_exchange_tx_v2_pb.MsgInstantBinaryOptionsMarketLaunchResponse,
+    "/injective.exchange.v2.MsgOffsetPositionResponse":
+        injective_exchange_tx_v2_pb.MsgOffsetPositionResponse,
 }

Please confirm the exact response type names in your updated proto (expected: MsgOffsetPositionResponse).



---

🏁 Script executed:

```shell
#!/bin/bash
# Check current state of the three maps in composer_v2.py
echo "=== REQUEST_TO_RESPONSE_TYPE_MAP ==="
rg -A 100 "REQUEST_TO_RESPONSE_TYPE_MAP = \{" pyinjective/composer_v2.py | head -120

echo ""
echo "=== GRPC_MESSAGE_TYPE_TO_CLASS_MAP ==="
rg -A 100 "GRPC_MESSAGE_TYPE_TO_CLASS_MAP = \{" pyinjective/composer_v2.py | head -120

echo ""
echo "=== GRPC_RESPONSE_TYPE_TO_CLASS_MAP ==="
rg -A 100 "GRPC_RESPONSE_TYPE_TO_CLASS_MAP = \{" pyinjective/composer_v2.py | head -120

echo ""
echo "=== Check for MsgOffsetPosition entries ==="
rg "MsgOffsetPosition" pyinjective/composer_v2.py

Length of output: 17873


🏁 Script executed:

#!/bin/bash
# Search for proto definitions related to MsgOffsetPosition
echo "=== Proto files with MsgOffsetPosition ==="
fd -e proto | xargs rg "MsgOffsetPosition" 2>/dev/null | head -20

echo ""
echo "=== Check if MsgOffsetPositionResponse exists in proto ==="
fd -e proto | xargs rg "MsgOffsetPositionResponse" 2>/dev/null

Length of output: 87242


🏁 Script executed:

#!/bin/bash
# Examine UnpackMsgExecResponse and UnpackTransactionMessages implementation
echo "=== UnpackMsgExecResponse implementation ==="
rg -A 15 "def UnpackMsgExecResponse" pyinjective/

echo ""
echo "=== UnpackTransactionMessages implementation ==="
rg -A 15 "def UnpackTransactionMessages" pyinjective/

Length of output: 5070


🏁 Script executed:

#!/bin/bash
# Check line numbers in composer_v2.py to validate diff accuracy
echo "=== Lines around 90-95 (REQUEST_TO_RESPONSE_TYPE_MAP) ==="
sed -n '85,100p' pyinjective/composer_v2.py

echo ""
echo "=== Lines around 192-200 (GRPC_MESSAGE_TYPE_TO_CLASS_MAP) ==="
sed -n '188,210p' pyinjective/composer_v2.py

echo ""
echo "=== Lines around 293-305 (GRPC_RESPONSE_TYPE_TO_CLASS_MAP) ==="
sed -n '290,310p' pyinjective/composer_v2.py

Length of output: 3173


Register MsgOffsetPosition in GRPC maps to prevent runtime KeyErrors.

The msg_offset_position method exposes a new message type, but the three GRPC registry maps lack entries for it. This will cause KeyError failures when UnpackMsgExecResponse or UnpackTransactionMessages process these messages.

Apply this diff:

--- a/pyinjective/composer_v2.py
+++ b/pyinjective/composer_v2.py
@@ -90,6 +90,8 @@ REQUEST_TO_RESPONSE_TYPE_MAP = {
     "MsgInstantBinaryOptionsMarketLaunch":
         injective_exchange_tx_v2_pb.MsgInstantBinaryOptionsMarketLaunchResponse,
+    "MsgOffsetPosition":
+        injective_exchange_tx_v2_pb.MsgOffsetPositionResponse,
 }
 
@@ -192,6 +194,8 @@ GRPC_MESSAGE_TYPE_TO_CLASS_MAP = {
     "/injective.exchange.v2.MsgInstantBinaryOptionsMarketLaunch":
         injective_exchange_tx_v2_pb.MsgInstantBinaryOptionsMarketLaunch,
+    "/injective.exchange.v2.MsgOffsetPosition":
+        injective_exchange_tx_v2_pb.MsgOffsetPosition,
 }
 
@@ -293,6 +297,8 @@ GRPC_RESPONSE_TYPE_TO_CLASS_MAP = {
     "/injective.exchange.v2.MsgInstantBinaryOptionsMarketLaunchResponse":
         injective_exchange_tx_v2_pb.MsgInstantBinaryOptionsMarketLaunchResponse,
+    "/injective.exchange.v2.MsgOffsetPositionResponse":
+        injective_exchange_tx_v2_pb.MsgOffsetPositionResponse,
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 40 to 88
_globals['_HISTORICALRPNL']._serialized_end=717
_globals['_HISTORICALDETAILEDPNL']._serialized_start=719
_globals['_HISTORICALDETAILEDPNL']._serialized_end=782
_globals['_VOLUMESREQUEST']._serialized_start=784
_globals['_VOLUMESREQUEST']._serialized_end=858
_globals['_VOLUMESRESPONSE']._serialized_start=860
_globals['_VOLUMESRESPONSE']._serialized_end=967
_globals['_HISTORICALVOLUMES']._serialized_start=969
_globals['_HISTORICALVOLUMES']._serialized_end=1016
_globals['_PNLLEADERBOARDREQUEST']._serialized_start=1019
_globals['_PNLLEADERBOARDREQUEST']._serialized_end=1148
_globals['_PNLLEADERBOARDRESPONSE']._serialized_start=1151
_globals['_PNLLEADERBOARDRESPONSE']._serialized_end=1374
_globals['_LEADERBOARDROW']._serialized_start=1376
_globals['_LEADERBOARDROW']._serialized_end=1480
_globals['_VOLLEADERBOARDREQUEST']._serialized_start=1483
_globals['_VOLLEADERBOARDREQUEST']._serialized_end=1612
_globals['_VOLLEADERBOARDRESPONSE']._serialized_start=1615
_globals['_VOLLEADERBOARDRESPONSE']._serialized_end=1838
_globals['_PNLLEADERBOARDFIXEDRESOLUTIONREQUEST']._serialized_start=1840
_globals['_PNLLEADERBOARDFIXEDRESOLUTIONREQUEST']._serialized_end=1958
_globals['_PNLLEADERBOARDFIXEDRESOLUTIONRESPONSE']._serialized_start=1961
_globals['_PNLLEADERBOARDFIXEDRESOLUTIONRESPONSE']._serialized_end=2199
_globals['_VOLLEADERBOARDFIXEDRESOLUTIONREQUEST']._serialized_start=2201
_globals['_VOLLEADERBOARDFIXEDRESOLUTIONREQUEST']._serialized_end=2319
_globals['_VOLLEADERBOARDFIXEDRESOLUTIONRESPONSE']._serialized_start=2322
_globals['_VOLLEADERBOARDFIXEDRESOLUTIONRESPONSE']._serialized_end=2560
_globals['_DENOMHOLDERSREQUEST']._serialized_start=2562
_globals['_DENOMHOLDERSREQUEST']._serialized_end=2649
_globals['_DENOMHOLDERSRESPONSE']._serialized_start=2651
_globals['_DENOMHOLDERSRESPONSE']._serialized_end=2773
_globals['_HOLDER']._serialized_start=2775
_globals['_HOLDER']._serialized_end=2850
_globals['_HISTORICALTRADESREQUEST']._serialized_start=2853
_globals['_HISTORICALTRADESREQUEST']._serialized_end=3069
_globals['_HISTORICALTRADESRESPONSE']._serialized_start=3072
_globals['_HISTORICALTRADESRESPONSE']._serialized_end=3245
_globals['_HISTORICALTRADE']._serialized_start=3248
_globals['_HISTORICALTRADE']._serialized_end=3735
_globals['_PRICELEVEL']._serialized_start=3737
_globals['_PRICELEVEL']._serialized_end=3829
_globals['_STREAMSPOTAVERAGEENTRIESREQUEST']._serialized_start=3831
_globals['_STREAMSPOTAVERAGEENTRIESREQUEST']._serialized_end=3890
_globals['_STREAMSPOTAVERAGEENTRIESRESPONSE']._serialized_start=3893
_globals['_STREAMSPOTAVERAGEENTRIESRESPONSE']._serialized_end=4036
_globals['_SPOTAVERAGEENTRY']._serialized_start=4039
_globals['_SPOTAVERAGEENTRY']._serialized_end=4191
_globals['_INJECTIVEARCHIVERRPC']._serialized_start=4194
_globals['_INJECTIVEARCHIVERRPC']._serialized_end=5506
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 | 🔴 Critical

🧩 Analysis chain

Descriptor index table updates look consistent. Check runtime versions.

Indices realign after inserting HistoricalDetailedPNL. Generated with Protobuf Python 5.26.1; ensure repo pins compatible versions of protobuf and grpcio to avoid runtime API mismatches (e.g., _registered_method usage).

If not already pinned, consider adding constraints such as:

  • protobuf >= 5.26, < 6
  • grpcio >= version that supports _registered_method (verify exact min in your CI matrix)

🏁 Script executed:

#!/bin/bash
# Find version constraints for protobuf/grpcio in the repo
fd -a 'pyproject.toml|poetry.lock|requirements*.txt|setup.cfg|setup.py' | xargs -I{} sh -c 'echo "== {} =="; sed -n "1,200p" "{}" | rg -nP "(protobuf|grpcio)" || true'

# Also scan for ruff config to potentially exclude generated files
fd -a 'pyproject.toml|ruff.toml|setup.cfg' | xargs -I{} sh -c 'echo "== {} =="; sed -n "1,200p" "{}" | rg -nP "tool\.ruff|ruff" || true'

Length of output: 213


Pin grpcio and grpcio-tools versions to match generated code compatibility.

grpcio versions released around 1.56.0+ (Jun 22, 2023) and later include support for modern gRPC features. The generated file uses patterns requiring a minimum grpcio version; however, the repository allows grpcio = "*" and grpcio-tools = "*", risking installation of incompatible versions at runtime.

Currently:

  • protobuf = "^5.26.1" ✓ correctly pinned to match generator
  • grpcio = "*" ✗ unconstrained
  • grpcio-tools = "*" ✗ unconstrained

Recommendation:

  • Pin grpcio >= 1.56, < 2 to ensure generated code compatibility
  • Pin grpcio-tools to a compatible range (same reasoning as grpcio)
  • Optionally exclude generated *_pb2.py files from linting in ruff.toml if not already configured
🤖 Prompt for AI Agents
In pyinjective/proto/exchange/injective_archiver_rpc_pb2.py around lines 40 to
88, the generated protobuf file indicates it depends on a minimum
grpcio/grpcio-tools feature set but the project currently allows grpcio = "*"
and grpcio-tools = "*"; update dependency constraints (e.g., pyproject.toml or
requirements) to pin grpcio >=1.56,<2 and grpcio-tools >=1.56,<2 (or a matching
compatible range) to ensure runtime compatibility with the generated code, and
optionally add the generated *_pb2.py files to ruff.toml ignores so linters skip
them.

Comment on lines +15 to +17
from pyinjective.proto.gogoproto import gogo_pb2 as gogoproto_dot_gogo__pb2
from pyinjective.proto.cosmos_proto import cosmos_pb2 as cosmos__proto_dot_cosmos__pb2

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 | 🔴 Critical

🧩 Analysis chain

Verify dependent proto Python modules are present and packaged.

These imports require bundled modules to exist in-tree and be included in wheels:

  • pyinjective.proto.gogoproto.gogo_pb2
  • pyinjective.proto.cosmos_proto.cosmos_pb2

Check presence and package init files:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Expect generated deps =="
fd -H -a 'pyinjective/proto/gogoproto/gogo_pb2.py' || true
fd -H -a 'pyinjective/proto/cosmos_proto/cosmos_pb2.py' || true

echo "== Verify package namespaces exist =="
for p in pyinjective pyinjective/proto pyinjective/proto/gogoproto pyinjective/proto/cosmos_proto pyinjective/proto/hyperlane pyinjective/proto/hyperlane/core pyinjective/proto/hyperlane/core/v1; do
  test -f "$p/__init__.py" && echo "ok: $p/__init__.py" || echo "missing: $p/__init__.py"
done

Length of output: 388


I need to gather more information about the proto directory structure and package configuration. Let me inspect the repository structure and packaging setup.

Let me check the repository structure for proto source files and packaging configuration.


---

🏁 Script executed:

```shell
#!/bin/bash
set -euo pipefail

echo "== Look for .proto files =="
fd -H -a '\\.proto$' | head -20

echo "== Check for proto directories with files =="
find pyinjective/proto -type d | head -20

echo "== Look for setup.py and pyproject.toml =="
fd -H -a '(setup\\.py|pyproject\\.toml)$' -type f

echo "== Check if pb2.py files exist anywhere =="
fd -H -a '\\.pb2\\.py$' | wc -l
fd -H -a '\\.pb2\\.py$' | head -10

Length of output: 773



---

🏁 Script executed:

```shell
#!/bin/bash
set -euo pipefail

echo "== List root files for setup.py/pyproject.toml =="
ls -la | grep -E '(setup|pyproject|MANIFEST)' || echo "None found with grep"

echo "== Direct list of gogoproto directory =="
ls -la pyinjective/proto/gogoproto/ 2>/dev/null || echo "gogoproto dir missing or empty"

echo "== Direct list of cosmos_proto directory =="
ls -la pyinjective/proto/cosmos_proto/ 2>/dev/null || echo "cosmos_proto dir missing or empty"

echo "== Direct list of hyperlane directory =="
ls -la pyinjective/proto/hyperlane/ 2>/dev/null || echo "hyperlane dir missing"

echo "== Check events_pb2.py existence =="
ls -la pyinjective/proto/hyperlane/core/v1/events_pb2.py 2>/dev/null || echo "events_pb2.py not found"

echo "== Head of events_pb2.py if it exists =="
head -20 pyinjective/proto/hyperlane/core/v1/events_pb2.py 2>/dev/null || echo "Cannot read events_pb2.py"

Length of output: 4507



---

🏁 Script executed:

```shell
#!/bin/bash
set -euo pipefail

echo "== pyproject.toml content =="
cat pyproject.toml

echo ""
echo "== MANIFEST.in content =="
cat MANIFEST.in

echo ""
echo "== Sample check: do other proto subdirs have __init__.py? =="
for dir in pyinjective/proto/amino pyinjective/proto/capability pyinjective/proto/cometbft; do
  test -f "$dir/__init__.py" && echo "ok: $dir/__init__.py" || echo "missing: $dir/__init__.py"
done

echo ""
echo "== Verify structure of hyperlane subdirs =="
find pyinjective/proto/hyperlane -name '__init__.py' -o -name '*.py' | head -30

Length of output: 4842


Add __init__.py to all proto package directories to enable imports.

The pb2 modules (gogo_pb2.py, cosmos_pb2.py) exist and are included in wheels via pyproject.toml and MANIFEST.in. However, the proto package directories lack __init__.py files, which prevents Python from recognizing them as packages. This causes ImportError at runtime.

Missing __init__.py in:

  • pyinjective/proto/gogoproto/
  • pyinjective/proto/cosmos_proto/
  • pyinjective/proto/hyperlane/
  • pyinjective/proto/hyperlane/core/
  • pyinjective/proto/hyperlane/core/v1/
  • All other proto subdirectories (amino, capability, cometbft, etc.)

Comment on lines +15 to +17
from hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2
from hyperlane.core.interchain_security.v1 import genesis_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_genesis__pb2
from hyperlane.core.post_dispatch.v1 import genesis_pb2 as hyperlane_dot_core_dot_post__dispatch_dot_v1_dot_genesis__pb2
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 | 🔴 Critical

🧩 Analysis chain

Broken import paths — switch to pyinjective-prefixed modules.

These imports won’t resolve under the current package layout. Use the pyinjective.proto.hyperlane.* paths or update codegen mappings.

Patch:

-from hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2
-from hyperlane.core.interchain_security.v1 import genesis_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_genesis__pb2
-from hyperlane.core.post_dispatch.v1 import genesis_pb2 as hyperlane_dot_core_dot_post__dispatch_dot_v1_dot_genesis__pb2
+from pyinjective.proto.hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2
+from pyinjective.proto.hyperlane.core.interchain_security.v1 import genesis_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_genesis__pb2
+from pyinjective.proto.hyperlane.core.post_dispatch.v1 import genesis_pb2 as hyperlane_dot_core_dot_post__dispatch_dot_v1_dot_genesis__pb2

If these modules don’t exist under pyinjective/proto/hyperlane/**, update the generator (Buf/protoc M<proto>=<py_pkg>) so all generated imports are consistent.


I'll verify the import paths by examining the repository structure and the actual file state.


🏁 Script executed:

#!/bin/bash
# Verify file existence and inspect imports
echo "=== Checking if file exists ==="
if [ -f "pyinjective/proto/hyperlane/core/v1/genesis_pb2.py" ]; then
  echo "File found"
  echo "=== Lines 15-17 of the file ==="
  sed -n '15,17p' "pyinjective/proto/hyperlane/core/v1/genesis_pb2.py"
  echo ""
  echo "=== First 30 lines (to see all imports) ==="
  head -30 "pyinjective/proto/hyperlane/core/v1/genesis_pb2.py"
else
  echo "File NOT found at pyinjective/proto/hyperlane/core/v1/genesis_pb2.py"
fi

echo ""
echo "=== Directory structure: pyinjective/proto/hyperlane ==="
if [ -d "pyinjective/proto/hyperlane" ]; then
  find pyinjective/proto/hyperlane -type d | head -20
else
  echo "Directory pyinjective/proto/hyperlane not found"
fi

echo ""
echo "=== Check if top-level hyperlane package exists ==="
if [ -d "hyperlane" ]; then
  echo "Top-level hyperlane directory exists"
  ls -la hyperlane/ | head -20
else
  echo "Top-level hyperlane directory NOT found"
fi

Length of output: 4332


🏁 Script executed:

#!/bin/bash
# Verify file existence and inspect imports
echo "=== Checking if file exists ==="
if [ -f "pyinjective/proto/hyperlane/core/v1/genesis_pb2.py" ]; then
  echo "File found"
  echo "=== Lines 15-17 of the file ==="
  sed -n '15,17p' "pyinjective/proto/hyperlane/core/v1/genesis_pb2.py"
  echo ""
  echo "=== First 35 lines (to see all imports) ==="
  head -35 "pyinjective/proto/hyperlane/core/v1/genesis_pb2.py"
else
  echo "File NOT found at pyinjective/proto/hyperlane/core/v1/genesis_pb2.py"
fi

echo ""
echo "=== Check directory structure ==="
if [ -d "pyinjective/proto/hyperlane" ]; then
  echo "pyinjective/proto/hyperlane exists:"
  find pyinjective/proto/hyperlane -type d | sort
else
  echo "Directory pyinjective/proto/hyperlane not found"
fi

echo ""
echo "=== Check if top-level hyperlane package exists ==="
if [ -d "hyperlane" ]; then
  echo "Top-level hyperlane exists: $(ls hyperlane/)"
else
  echo "Top-level hyperlane NOT found"
fi

echo ""
echo "=== Check for __init__.py files in proto paths ==="
find pyinjective/proto -name "__init__.py" 2>/dev/null | head -20

Length of output: 4925


Let me check if this pattern exists in other generated files and look for generator configuration:


🏁 Script executed:

#!/bin/bash
# Check other hyperlane _pb2.py files for the same import pattern
echo "=== Checking other hyperlane _pb2.py files for broken imports ==="
find pyinjective/proto/hyperlane -name "*_pb2.py" -type f | while read file; do
  if grep -q "^from hyperlane\." "$file"; then
    echo "File: $file"
    grep "^from hyperlane\." "$file" | head -3
    echo ""
  fi
done

echo ""
echo "=== Check for generator config files ==="
find . -maxdepth 3 -type f \( -name "buf.gen.yaml" -o -name "buf.yaml" -o -name "setup.py" -o -name "setup.cfg" \) 2>/dev/null | head -10

echo ""
echo "=== Inspect pyinjective/proto/__init__.py ==="
if [ -f "pyinjective/proto/__init__.py" ]; then
  echo "Content:"
  cat pyinjective/proto/__init__.py
else
  echo "File not found"
fi

echo ""
echo "=== Check if hyperlane subpackages have __init__.py ==="
find pyinjective/proto/hyperlane -name "__init__.py" 2>/dev/null

Length of output: 1952


Let me inspect the generator configuration to confirm the mapping issue:


🏁 Script executed:

#!/bin/bash
echo "=== buf.gen.yaml content ==="
cat ./buf.gen.yaml

echo ""
echo "=== Check for any protobuf generation scripts ==="
find . -maxdepth 2 -name "*.sh" -o -name "Makefile" 2>/dev/null | xargs grep -l "buf\|protoc" 2>/dev/null | head -5

Length of output: 1224


Fix broken hyperlane imports — these will fail at runtime since the top-level hyperlane package doesn't exist.

The imports on lines 15–17 cannot resolve. The codebase structure only has pyinjective/proto/hyperlane/, not a top-level hyperlane/ package. This issue affects all 8+ generated hyperlane protobuf files.

Update all three imports to use the pyinjective.proto.hyperlane.* prefix:

-from hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2
-from hyperlane.core.interchain_security.v1 import genesis_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_genesis__pb2
-from hyperlane.core.post_dispatch.v1 import genesis_pb2 as hyperlane_dot_core_dot_post__dispatch_dot_v1_dot_genesis__pb2
+from pyinjective.proto.hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2
+from pyinjective.proto.hyperlane.core.interchain_security.v1 import genesis_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_genesis__pb2
+from pyinjective.proto.hyperlane.core.post_dispatch.v1 import genesis_pb2 as hyperlane_dot_core_dot_post__dispatch_dot_v1_dot_genesis__pb2

Also update buf.gen.yaml to add module mappings (e.g., M hyperlane/core/v1/types.proto=pyinjective.proto.hyperlane.core.v1) so the entire hyperlane module tree regenerates correctly on next buf generate.

📝 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
from hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2
from hyperlane.core.interchain_security.v1 import genesis_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_genesis__pb2
from hyperlane.core.post_dispatch.v1 import genesis_pb2 as hyperlane_dot_core_dot_post__dispatch_dot_v1_dot_genesis__pb2
from pyinjective.proto.hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2
from pyinjective.proto.hyperlane.core.interchain_security.v1 import genesis_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_genesis__pb2
from pyinjective.proto.hyperlane.core.post_dispatch.v1 import genesis_pb2 as hyperlane_dot_core_dot_post__dispatch_dot_v1_dot_genesis__pb2
🤖 Prompt for AI Agents
In pyinjective/proto/hyperlane/core/v1/genesis_pb2.py around lines 15 to 17 the
import paths use a top-level hyperlane package that doesn't exist; change the
three imports to use the repo package prefix (pyinjective.proto.hyperlane...),
e.g. pyinjective.proto.hyperlane.core.v1.types_pb2 and similar for
interchain_security.v1.genesis_pb2 and post_dispatch.v1.genesis_pb2 so they
resolve at runtime; additionally update buf.gen.yaml to add module mappings for
the hyperlane protos (for example M
hyperlane/core/v1/types.proto=pyinjective.proto.hyperlane.core.v1 and
corresponding entries for other files) so regenerated files use the correct
package names.



from pyinjective.proto.cosmos.base.query.v1beta1 import pagination_pb2 as cosmos_dot_base_dot_query_dot_v1beta1_dot_pagination__pb2
from hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2
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 | 🔴 Critical

🧩 Analysis chain

Import path mismatch will likely break imports.

This line imports from hyperlane.core.v1, while all other deps use pyinjective.proto.*. Unless the repo adds pyinjective/proto to sys.path at runtime, this will raise ImportError. Use the pyinjective.proto path for consistency.

Apply this diff:

-from hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2
+from pyinjective.proto.hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2

Run to confirm no remaining inconsistent imports:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Scanning for top-level hyperlane imports in pb2 files..."
rg -nP --glob 'pyinjective/**' $'^from\s+hyperlane\.core\.v1\s+import\s+types_pb2' -C2 || true

echo "Check presence of generated types file paths:"
fd -a 'types_pb2.py' | grep -E 'hyperlane/core/v1/types_pb2\.py' || true

echo "Verify whether a top-level hyperlane package exists:"
test -f hyperlane/__init__.py && echo "Top-level hyperlane package present" || echo "No top-level hyperlane package"

Length of output: 1510



---

🏁 Script executed:

```shell
#!/bin/bash
set -euo pipefail

echo "=== Searching for sys.path manipulations ==="
rg -n 'sys\.path' --type=py -C2 || echo "No sys.path manipulations found"

echo ""
echo "=== Searching for PYTHONPATH or setup configurations ==="
rg -n 'PYTHONPATH|namespace_packages|package_dir' --type=py || echo "No PYTHONPATH/namespace config found"

echo ""
echo "=== Count total affected files with top-level hyperlane imports ==="
rg --glob 'pyinjective/**' $'^from\s+hyperlane\.core' --count-matches 2>/dev/null | wc -l || echo "0"

echo ""
echo "=== List all affected import lines ==="
rg --glob 'pyinjective/**' -n $'^from\s+hyperlane\.' | head -20

Length of output: 3380


🏁 Script executed:

#!/bin/bash
# Quick verification: if these were meant to be top-level, verify no __init__.py exists
test -f hyperlane/__init__.py && echo "Top-level hyperlane exists" || echo "Confirmed: no top-level hyperlane package"

Length of output: 41


Import path mismatch affects 12 generated protobuf files and will cause ImportError at runtime.

Top-level hyperlane.* imports exist in proto-generated files under pyinjective/proto/hyperlane/ but no top-level hyperlane package exists in the repository. Without sys.path manipulation (which is absent), these imports will fail. All 12 affected files need the import paths prefixed with pyinjective.proto.:

Affected files:

  • pyinjective/proto/hyperlane/core/v1/query_pb2.py (line 16)
  • pyinjective/proto/hyperlane/core/v1/genesis_pb2.py (lines 15-17)
  • pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py (line 5)
  • pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py (line 5)
  • pyinjective/proto/hyperlane/warp/v1/query_pb2.py (line 17)
  • pyinjective/proto/hyperlane/warp/v1/tx_pb2.py (line 20)
  • pyinjective/proto/hyperlane/warp/v1/genesis_pb2.py (line 15)
  • pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py (line 5)
  • pyinjective/proto/hyperlane/warp/v1/tx_pb2_grpc.py (line 5)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2.py (line 19)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2.py (line 19)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2.py (line 15)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2_grpc.py (line 5)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2_grpc.py (line 5)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2.py (line 18)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py (line 5)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py (line 5)

Example fix:

-from hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2
+from pyinjective.proto.hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2

Apply the same pattern to all remaining 11 files.

🤖 Prompt for AI Agents
In pyinjective/proto/hyperlane/core/v1/query_pb2.py around line 16, the
generated import uses a top-level "hyperlane.core.v1.types_pb2" path which will
raise ImportError because there is no top-level hyperlane package; update the
import to be package-relative by prefixing with "pyinjective.proto." (e.g.
"pyinjective.proto.hyperlane.core.v1.types_pb2") and apply the identical change
to the other 11+ affected generated proto files listed in the review so all
internal proto imports use the "pyinjective.proto." prefix.

Comment on lines +1 to +3
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: hyperlane/warp/v1/genesis.proto
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 | 🔴 Critical

🧩 Analysis chain

General: generated code LGTM.

Descriptors and message wiring look standard; no manual edits detected.

Quick package layout check (namespace vs regular packages):


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Verify namespace/package init files exist so imports like
# pyinjective.proto.hyperlane.warp.v1.* resolve
for d in pyinjective pyinjective/proto pyinjective/proto/hyperlane pyinjective/proto/hyperlane/warp pyinjective/proto/hyperlane/warp/v1; do
  test -d "$d" || { echo "missing dir: $d"; exit 1; }
done
# If not using PEP 420 namespaces, ensure __init__.py files exist
fd -H "__init__.py" pyinjective/proto/hyperlane/warp/v1 >/dev/null || echo "note: consider __init__.py if not using namespace packages"

Length of output: 0


I need more detailed verification since the previous output was ambiguous. Let me check the actual package structure and init.py files:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking v1 directory contents ==="
ls -la pyinjective/proto/hyperlane/warp/v1/ 2>/dev/null | head -20

echo ""
echo "=== Checking for __init__.py at each level ==="
for d in pyinjective pyinjective/proto pyinjective/proto/hyperlane pyinjective/proto/hyperlane/warp pyinjective/proto/hyperlane/warp/v1; do
  if [ -f "$d/__init__.py" ]; then
    echo "$d/__init__.py: EXISTS"
  else
    echo "$d/__init__.py: MISSING"
  fi
done

echo ""
echo "=== Checking genesis_pb2.py ==="
ls -lh pyinjective/proto/hyperlane/warp/v1/genesis_pb2.py 2>/dev/null || echo "File not found"

Length of output: 1218


Add missing __init__.py files to pyinjective/proto/hyperlane, pyinjective/proto/hyperlane/warp, and pyinjective/proto/hyperlane/warp/v1 directories.

The codebase uses traditional packages (pyinjective and proto have init.py), but the hyperlane subtree lacks init.py at all levels. This will break imports of generated protobuf code like from pyinjective.proto.hyperlane.warp.v1 import genesis_pb2. Each intermediate directory in the module path requires an init.py file.

🤖 Prompt for AI Agents
In pyinjective/proto/hyperlane/warp/v1/genesis_pb2.py lines 1-3, the generated
protobuf module expects the package path pyinjective.proto.hyperlane.warp.v1 to
be a proper Python package, but the intermediate directories
(pyinjective/proto/hyperlane, pyinjective/proto/hyperlane/warp, and
pyinjective/proto/hyperlane/warp/v1) are missing __init__.py files; add empty
(or with package metadata) __init__.py files to each of those three directories
so imports like from pyinjective.proto.hyperlane.warp.v1 import genesis_pb2
resolve correctly.

# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: hyperlane/warp/v1/genesis.proto
# Protobuf Python Version: 5.26.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 | 🔴 Critical

🧩 Analysis chain

Ensure protobuf runtime compatibility.

File generated with “Protobuf Python Version: 5.26.1”. Pin runtime to a compatible version to avoid Descriptor/Builder API mismatches.

Use this to check pinned versions:

Expected: protobuf >= 5.26 and grpcio compatible with your generators.


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Search dependency files for protobuf/grpc pins
fd -H -a 'requirements*.txt|setup.cfg|pyproject.toml|setup.py|Pipfile' \
  | xargs -I {} sh -c 'echo "== {} =="; rg -n "protobuf|grpcio" {} || true'

Length of output: 309



---

🌐 Web query:

```web
grpcio protobuf 5.26 compatibility version requirements

💡 Result:

Short answer

  • grpcio itself has historically been compatible with protobuf 4.x; many grpc Python helper packages (grpcio-tools) constrained protobuf to <5.0dev for a long time. See the open grpc issue about adding support for protobuf 5.26.0. [1]
  • Newer grpc-related packages (notably grpcio-status and recent grpcio releases) now declare support for Protobuf 5.x and require protobuf >=5.26.1, <6.0dev. Example dependency metadata shows grpcio-status requires protobuf >=5.26.1,<6.0dev. [2][3]
  • Protobuf 5.x (5.26.x) was released in Q1 2024; follow the Protobuf cross-version/runtime guarantees when mixing generated code and runtime (runtime must be >= the gencode version). [4]

If you tell me which grpc/grpcio package/version you plan to use (grpcio, grpcio-tools, grpcio-status and their versions), I’ll give the exact protobuf version requirement for that package and recommended pin.

Sources

  1. grpc GitHub issue about supporting protobuf 5.26.0. [1]
  2. grpcio-status dependency metadata (shows protobuf >=5.26.1,<6.0dev). [2]
  3. Examples / packaging notes showing grpcio-tools historically constrained protobuf <5.0dev. [1][3]
  4. Protobuf version support / cross-version runtime guarantee. [4]

References:
[1] grpc/grpc#36142
[2] grpcio-status dependency listing / package metadata (rpm/PyPI).
[3] Example reports of grpcio-tools requiring protobuf <5.0dev (issue threads & packaging).
[4] https://protobuf.dev/support/version-support/



---

🌐 Web query:

```web
grpcio-tools protobuf 5.26.1 support compatibility when added

💡 Result:

grpcio-tools began allowing protobuf >=5.26.1 starting with the 1.65.x releases (the dependency on protobuf was changed to <6.0dev,>=5.26.1 in grpcio-tools 1.65.1 — released mid‑July 2024). [1][2]

Sources:

  • grpcio-tools 1.65.1 dependency listing (protobuf <6.0dev, >=5.26.1). [1]
  • grpcio-tools 1.65.1 release date (July 17–18, 2024). [2]


---

🏁 Script executed:

```shell
#!/bin/bash
set -euo pipefail
# Extract grpcio-tools version from Pipfile.lock
rg -A5 '"grpcio-tools"' /home/jailuser/git/Pipfile.lock | head -20

Length of output: 413



---

🏁 Script executed:

```shell
#!/bin/bash
set -euo pipefail
# Parse Pipfile.lock JSON to get grpcio-tools version
python3 << 'EOF'
import json
with open('/home/jailuser/git/Pipfile.lock', 'r') as f:
    data = json.load(f)
    if 'default' in data and 'grpcio-tools' in data['default']:
        print(f"grpcio-tools version: {data['default']['grpcio-tools'].get('version', 'N/A')}")
    if 'develop' in data and 'grpcio-tools' in data['develop']:
        print(f"grpcio-tools (dev) version: {data['develop']['grpcio-tools'].get('version', 'N/A')}")
EOF

Length of output: 30


Pin grpcio-tools to >=1.65.1 to ensure protobuf 5.26.1 compatibility.

Current Pipfile.lock locks grpcio-tools to 1.57.0, which requires protobuf <5.0dev. This conflicts with protobuf 5.26.1 pinned in pyproject.toml. Update pyproject.toml and Pipfile to specify grpcio-tools >= "1.65.1" (first version supporting protobuf >=5.26.1).

@aarmoa aarmoa force-pushed the cp-652/update_protos_for_v1_17_0 branch from 0a37ea0 to 4d134c8 Compare October 23, 2025 13:06
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: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
tests/test_composer_v2.py (2)

911-935: Duplicate test name overrides earlier test. Remove the duplicate.

The method test_msg_privileged_execute_contract is defined twice; the latter overrides the former, dropping one test from execution.

Apply this diff to remove the duplicate:

-    def test_msg_privileged_execute_contract(self, basic_composer):
-        sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0"
-        contract_address = "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7"
-        data = "test_data"
-        funds = "100inj,420peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7"
-
-        message = basic_composer.msg_privileged_execute_contract(
-            sender=sender,
-            contract_address=contract_address,
-            data=data,
-            funds=funds,
-        )
-
-        expected_message = {
-            "sender": sender,
-            "funds": funds,
-            "contractAddress": contract_address,
-            "data": data,
-        }
-        dict_message = json_format.MessageToDict(
-            message=message,
-            always_print_fields_with_no_presence=True,
-        )
-        assert dict_message == expected_message

Also applies to: 2128-2152


1073-1114: Duplicate test name; rename the second to reflect Binary Options context.

Two methods named test_msg_cancel_derivative_order exist; the latter overrides the former. Rename the second to keep both.

-    def test_msg_cancel_derivative_order(self, basic_composer):
+    def test_msg_cancel_binary_options_order(self, basic_composer):

Also applies to: 1318-1359

♻️ Duplicate comments (13)
pyinjective/proto/hyperlane/core/v1/query_pb2.py (1)

16-16: Import path mismatch will cause ImportError - already flagged in previous review.

This import uses top-level hyperlane.core.v1 while all other imports correctly use pyinjective.proto.* prefix. As documented in the previous review, this affects 12+ generated files and will fail at runtime because no top-level hyperlane package exists.

Apply this diff:

-from hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2
+from pyinjective.proto.hyperlane.core.v1 import types_pb2 as hyperlane_dot_core_dot_v1_dot_types__pb2
pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py (1)

5-5: Import path mismatch will cause ImportError - already flagged in previous review.

This import uses top-level hyperlane.core.v1 instead of the package-relative pyinjective.proto.hyperlane.core.v1. As documented in the previous review, this critical issue affects 12+ generated files and will cause ImportError at runtime.

Apply this diff:

-from hyperlane.core.v1 import query_pb2 as hyperlane_dot_core_dot_v1_dot_query__pb2
+from pyinjective.proto.hyperlane.core.v1 import query_pb2 as hyperlane_dot_core_dot_v1_dot_query__pb2
pyinjective/proto/hyperlane/core/v1/events_pb2.py (1)

15-16: Missing __init__.py files will cause ImportError (duplicate concern).

This issue was already flagged in a previous review: the imports on these lines require __init__.py files in all proto package directories to make them recognizable as Python packages. Without them, runtime imports will fail.

Required __init__.py files:

  • pyinjective/proto/gogoproto/__init__.py
  • pyinjective/proto/cosmos_proto/__init__.py
  • pyinjective/proto/hyperlane/__init__.py
  • pyinjective/proto/hyperlane/core/__init__.py
  • pyinjective/proto/hyperlane/core/v1/__init__.py
pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2.py (2)

18-18: Broken import path for types_pb2 (must use pyinjective.proto.hyperlane...).

This will fail at runtime unless hyperlane is importable as a top-level package. Align with repo package root.

-from hyperlane.core.interchain_security.v1 import types_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_types__pb2
+from pyinjective.proto.hyperlane.core.interchain_security.v1 import types_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_types__pb2

57-57: Garbled amino option for MsgSetRoutingIsmDomain; fix upstream proto and regenerate.

Serialized option shows hyperlane/v1/MsgCreateRoMsgSetRoutingIsmDomainutingIsm. Likely intended: hyperlane/v1/MsgSetRoutingIsmDomain. Do not hand-edit pb2; correct the .proto annotation and regenerate.

examples/chain_client/exchange/30_MsgOffsetPosition.py (4)

1-7: Round gas price up; avoid rounding down with int()

Use math.ceil for the 1.1x bump; import math.

-import asyncio
+import asyncio
+import math
@@
-# adjust gas price ... broadcasted
-gas_price = int(gas_price * 1.1)
+# adjust gas price ... broadcasted
+gas_price = math.ceil(gas_price * 1.1)
@@
-# adjust gas price ... broadcasted
-gas_price = int(gas_price * 1.1)
+# adjust gas price ... broadcasted
+gas_price = math.ceil(gas_price * 1.1)

Also applies to: 25-27, 61-64


67-68: Prefer asyncio.run(main())

Simpler and safer entrypoint for modern Python.

-if __name__ == "__main__":
-    asyncio.get_event_loop().run_until_complete(main())
+if __name__ == "__main__":
+    asyncio.run(main())

15-16: Validate INJECTIVE_PRIVATE_KEY before use

Guard against None/empty to avoid crashes in PrivateKey.from_hex and broadcaster init.

Apply:

 dotenv.load_dotenv()
 configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
+if not configured_private_key:
+    raise ValueError("INJECTIVE_PRIVATE_KEY env var is required for this example.")

43-46: Use a list for offsetting_subaccount_ids (repeated field)

composer.msg_offset_position expects List[str]; a set can break type/ordering.

-offsetting_subaccount_ids = {
+offsetting_subaccount_ids = [
     "0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
     "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
-}
+]
pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2.py (1)

15-16: Broken import path — prefix with pyinjective.proto

Importing from hyperlane.* will fail without a top-level hyperlane package.

-from hyperlane.core.post_dispatch.v1 import types_pb2 as hyperlane_dot_core_dot_post__dispatch_dot_v1_dot_types__pb2
+from pyinjective.proto.hyperlane.core.post_dispatch.v1 import types_pb2 as hyperlane_dot_core_dot_post__dispatch_dot_v1_dot_types__pb2

Run to find and list all similar imports:

#!/bin/bash
rg -nP '^\s*(from|import)\s+hyperlane\.' -C1 --type=py
examples/chain_client/exchange/9_MsgBatchUpdateOrders.py (1)

113-115: Avoid Decimal(float); use string literal to prevent FP rounding.

Lines 113 and 115 use Decimal(0.1) which can introduce floating-point rounding errors. Use string literals instead: Decimal("0.1").

Apply this diff to fix the float literal usage:

-            quantity=Decimal(0.1),
+            quantity=Decimal("0.1"),
             margin=composer.calculate_margin(
-                quantity=Decimal(0.1), price=Decimal(25100), leverage=Decimal(1), is_reduce_only=False
+                quantity=Decimal("0.1"), price=Decimal(25100), leverage=Decimal(1), is_reduce_only=False
             ),
pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2.py (1)

19-19: Fix broken hyperlane import path.

The generated module still imports types_pb2 via from hyperlane.core.post_dispatch.v1 import ..., but in this repo the package lives under pyinjective.proto.hyperlane.core.post_dispatch.v1. At runtime this statement raises ModuleNotFoundError, so every consumer of the new query bindings fails immediately. Please switch the import to the fully qualified package path (and update the generator config so future regenerations stay fixed).

-from hyperlane.core.post_dispatch.v1 import types_pb2 as hyperlane_dot_core_dot_post__dispatch_dot_v1_dot_types__pb2
+from pyinjective.proto.hyperlane.core.post_dispatch.v1 import types_pb2 as hyperlane_dot_core_dot_post__dispatch_dot_v1_dot_types__pb2
pyinjective/composer_v2.py (1)

1210-1218: Critical: MsgOffsetPosition still missing from GRPC registry maps.

This issue was flagged in a previous review and remains unresolved. The msg_offset_position method creates MsgOffsetPosition messages, but the three GRPC registry maps (REQUEST_TO_RESPONSE_TYPE_MAP, GRPC_MESSAGE_TYPE_TO_CLASS_MAP, GRPC_RESPONSE_TYPE_TO_CLASS_MAP) lack entries for this message type. This will cause KeyError failures when UnpackMsgExecResponse or UnpackTransactionMessages process these messages at runtime.

Apply this diff to register MsgOffsetPosition and its response:

--- a/pyinjective/composer_v2.py
+++ b/pyinjective/composer_v2.py
@@ -90,6 +90,8 @@ REQUEST_TO_RESPONSE_TYPE_MAP = {
     "MsgInstantBinaryOptionsMarketLaunch":
         injective_exchange_tx_v2_pb.MsgInstantBinaryOptionsMarketLaunchResponse,
+    "MsgOffsetPosition":
+        injective_exchange_tx_v2_pb.MsgOffsetPositionResponse,
 }
 
@@ -192,6 +194,8 @@ GRPC_MESSAGE_TYPE_TO_CLASS_MAP = {
     "/injective.exchange.v2.MsgInstantBinaryOptionsMarketLaunch":
         injective_exchange_tx_v2_pb.MsgInstantBinaryOptionsMarketLaunch,
+    "/injective.exchange.v2.MsgOffsetPosition":
+        injective_exchange_tx_v2_pb.MsgOffsetPosition,
 }
 
@@ -293,6 +297,8 @@ GRPC_RESPONSE_TYPE_TO_CLASS_MAP = {
     "/injective.exchange.v2.MsgInstantBinaryOptionsMarketLaunchResponse":
         injective_exchange_tx_v2_pb.MsgInstantBinaryOptionsMarketLaunchResponse,
+    "/injective.exchange.v2.MsgOffsetPositionResponse":
+        injective_exchange_tx_v2_pb.MsgOffsetPositionResponse,
 }
🧹 Nitpick comments (20)
pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py (1)

44-70: Silence lint on generated code (Ruff ARG002)

Unused request/context params in unimplemented stubs are expected in generated files. Exclude these paths or add per-file-ignores to avoid noise.

Example (ruff.toml):

+[tool.ruff]
+extend-exclude = ["pyinjective/proto/**"]
+# Or, per-file ignores:
+[tool.ruff.per-file-ignores]
+"pyinjective/proto/**" = ["ARG002"]
pyinjective/proto/injective/peggy/v1/msgs_pb2_grpc.py (1)

194-201: Generated servicer methods trigger Ruff ARG002; exclude generated code from lint.
Don’t hand-edit; configure Ruff to ignore generated files.

Apply one of these (prefer A):

  • A) Exclude the directory
+[tool.ruff]
+extend-exclude = ["pyinjective/proto"]
  • B) Or per-file ignore (if you already use per-file-ignores)
+[tool.ruff.per-file-ignores]
+"pyinjective/proto/**/*.py" = ["ALL"]

Also applies to: 202-209, 210-216

pyinjective/proto/hyperlane/core/interchain_security/v1/events_pb2.py (2)

15-17: Generated imports may appear unused; exclude _pb2 files from lint/mypy.

gogo_pb2 and cosmos_pb2 are imported to register options; linters can flag F401/F811 and mypy can be noisy. Exclude generated files to keep CI clean.

Examples (pick what you use):

  • setup.cfg (flake8):
[flake8]
per-file-ignores =
  pyinjective/proto/**/_pb2.py: F401,F811,E501
  • mypy.ini or setup.cfg (mypy):
[mypy]
exclude = (?x)
  ^pyinjective/proto/.*_pb2\.py$
  • pyproject.toml (ruff):
[tool.ruff]
extend-exclude = ["pyinjective/proto/**/_pb2.py"]

21-24: Optional: ensure C‑descriptor fastpath for better import speed.

If possible, use protobuf wheels with C extensions so _USE_C_DESCRIPTORS is true; imports and message creation are faster.

pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py (1)

60-119: Silence ARG002 in generated servicer methods or exclude generated tree from lint.

Ruff flags unused request params. Prefer excluding generated code (pyinjective/proto/**) from lint, or add a file header ignore.

Options:

  • Configure Ruff: exclude pyinjective/proto/** from lint.
  • Or add at top of file: # ruff: noqa: ARG002 (keep generated file unedited if possible).
pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2.py (1)

26-26: Consider emitting correct Python package path via proto option to avoid hyperlane.* in generated code.

Set python_package in the proto (or configure the generator) to pyinjective.proto.hyperlane.core.interchain_security.v1 so imports and module registration align without post-edits; then regenerate.

Example (in tx.proto header):

option (python_package) = "pyinjective.proto.hyperlane.core.interchain_security.v1";
pyinjective/proto/hyperlane/warp/v1/query_pb2.py (1)

1-76: Generated file: exclude from lint/type-check.

Servicer stubs and descriptor blobs will trigger false positives. Exclude pyinjective/proto/** from Ruff/mypy rather than editing generated code.

Example Ruff config:

+[tool.ruff]
+exclude = ["pyinjective/proto/**"]
pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py (2)

5-6: Import path must resolve hyperlane.warp.v1.query_pb2.

Same concern as pb2: confirm that hyperlane.* is importable in your runtime (via packaging or explicit sys.path injection). See the import check script in the other comment.

If unresolved, adjust generator imports or expose pyinjective/proto on sys.path in pyinjective/__init__.py.


49-82: Lint noise in generated Servicer (unused args).

Ruff ARG002 warnings on request/context are expected here. Prefer per-path excludes instead of editing generated code.

Ruff:

+[tool.ruff]
+per-file-ignores = {"pyinjective/proto/**" = ["ARG002"]}
pyinjective/proto/hyperlane/warp/v1/tx_pb2.py (2)

20-21: Import path consistency for hyperlane.warp.v1.types_pb2.

Ensure hyperlane.* is resolvable at runtime (via packaging or explicit sys.path exposure). See earlier import verification script.

If unresolved, update generator imports or add explicit exposure in pyinjective/__init__.py.


1-121: Generated file: exclude from lint/type-check.

Recommend excluding pyinjective/proto/** from Ruff/mypy.

Ruff example shown in prior comments.

pyinjective/proto/hyperlane/warp/v1/tx_pb2_grpc.py (3)

5-6: Top-level import path check.

from hyperlane.warp.v1 import tx_pb2 must resolve; verify environment exposes hyperlane.* as importable. See earlier script.

Expose pyinjective/proto on sys.path or adjust generator imports.


109-151: grpc feature usage: registered handlers support.

Uses server.add_registered_method_handlers and _registered_method=True. Verify grpcio version compatibility as noted for Query service.

(Use the grpc version script shared earlier.)

Pin grpcio to a validated minimum in packaging.


59-107: Generated Servicer unused-arg warnings.

Ignore via tooling rather than editing generated code.

Ruff per-file-ignores for ARG002 on pyinjective/proto/**.

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

90-102: New RPC wrappers look good; tighten typing and handle “unspecified denoms”.

  • Return types are proto messages, not Dict[str, Any]. Prefer concrete response types for clarity.
  • For denoms, passing None into a repeated field can be ambiguous. Construct the request and only set denoms when provided to preserve “unspecified returns all” semantics.

Apply these diffs:

@@
-    async def fetch_auction_exchange_transfer_denom_decimal(self, denom: str) -> Dict[str, Any]:
+    async def fetch_auction_exchange_transfer_denom_decimal(
+        self, denom: str
+    ) -> exchange_query_pb.QueryAuctionExchangeTransferDenomDecimalResponse:
@@
-    async def fetch_auction_exchange_transfer_denom_decimals(
-        self, denoms: Optional[List[str]] = None
-    ) -> Dict[str, Any]:
-        request = exchange_query_pb.QueryAuctionExchangeTransferDenomDecimalsRequest(denoms=denoms)
+    async def fetch_auction_exchange_transfer_denom_decimals(
+        self, denoms: Optional[List[str]] = None
+    ) -> exchange_query_pb.QueryAuctionExchangeTransferDenomDecimalsResponse:
+        request = exchange_query_pb.QueryAuctionExchangeTransferDenomDecimalsRequest()
+        if denoms:
+            request.denoms.extend(denoms)
@@
-    async def fetch_open_interest(self, market_id: str) -> Dict[str, Any]:
+    async def fetch_open_interest(
+        self, market_id: str
+    ) -> exchange_query_pb.QueryOpenInterestResponse:

Also applies to: 656-661

tests/test_composer_v2.py (3)

1634-1644: Minor: fix variable name typo for clarity.

reduce_margin_ration → reduce_margin_ratio for consistency with others.

-        reduce_margin_ration = Decimal("3")
+        reduce_margin_ratio = Decimal("3")
@@
-        expected_reduce_margin_ratio = Token.convert_value_to_extended_decimal_format(value=reduce_margin_ration)
+        expected_reduce_margin_ratio = Token.convert_value_to_extended_decimal_format(value=reduce_margin_ratio)
@@
-            new_reduce_margin_ratio=reduce_margin_ration,
+            new_reduce_margin_ratio=reduce_margin_ratio,

2344-2640: Chain stream filter tests (explicit and default “*”) — good additions.

Covers all filters with explicit args and wildcard defaults; this guards composer helpers. One follow-up: composer’s chain_stream_oracle_price_filter return type hint currently points to PositionsFilter (see composer snippet) though it returns OraclePriceFilter. Please fix the annotation.

Proposed change in pyinjective/composer_v2.py:

-def chain_stream_oracle_price_filter(
-        self,
-        symbols: Optional[List[str]] = None,
-    ) -> chain_stream_v2_query.PositionsFilter:
+def chain_stream_oracle_price_filter(
+        self,
+        symbols: Optional[List[str]] = None,
+    ) -> chain_stream_v2_query.OraclePriceFilter:

2576-2576: Static analysis (Gitleaks) likely false positives.

The flagged strings are Injective bech32 addresses (inj1…), not API keys. Consider allow-listing the pattern to avoid noise.

Add a rule to your gitleaks config:

# .gitleaks.toml
[[rules]]
description = "Allowlist Injective bech32 addresses"
id = "allow-injective-bech32"
regex = '''inj1[ac-hj-np-z02-9]{38}'''
[allowlist]
description = "Known safe address pattern"
regexes = ['''inj1[ac-hj-np-z02-9]{38}''']

Also applies to: 2345-2345

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

1-2866: Reduce test duplication via parametrization/helpers (optional).

Large repeated patterns (orderbook, orders, markets) can be parameterized or factored into fixtures/helpers to cut boilerplate and ease future proto changes.


396-414: Inconsistent numeric conversion: denom/decimals returned as strings while baseDecimals/quoteDecimals are ints. Tests (tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py, ~lines 396–442) assert Auction denom decimal(s) as strings but SpotMarket base/quote decimals as integers — either document the API’s numeric-to-string conversion policy or normalize the API layer so numeric fields use a consistent type in JSON responses.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a37ea0 and 4d134c8.

📒 Files selected for processing (88)
  • Makefile (1 hunks)
  • buf.gen.yaml (1 hunks)
  • examples/chain_client/7_ChainStream.py (2 hunks)
  • examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py (1 hunks)
  • examples/chain_client/exchange/25_MsgUpdateDerivativeMarket.py (1 hunks)
  • examples/chain_client/exchange/30_MsgOffsetPosition.py (1 hunks)
  • examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py (1 hunks)
  • examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py (1 hunks)
  • examples/chain_client/exchange/9_MsgBatchUpdateOrders.py (2 hunks)
  • examples/chain_client/exchange/query/66_OpenInterest.py (1 hunks)
  • examples/chain_client/exchange/query/8_AuctionExchangeTransferDenomDecimal.py (1 hunks)
  • examples/chain_client/exchange/query/9_AuctionExchangeTransferDenomDecimals.py (1 hunks)
  • pyinjective/async_client_v2.py (5 hunks)
  • pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (2 hunks)
  • pyinjective/client/chain/grpc_stream/chain_grpc_chain_stream.py (2 hunks)
  • pyinjective/composer_v2.py (13 hunks)
  • pyinjective/proto/exchange/injective_archiver_rpc_pb2.py (2 hunks)
  • pyinjective/proto/exchange/injective_archiver_rpc_pb2_grpc.py (4 hunks)
  • pyinjective/proto/exchange/injective_auction_rpc_pb2.py (2 hunks)
  • pyinjective/proto/exchange/injective_megavault_rpc_pb2.py (2 hunks)
  • pyinjective/proto/google/longrunning/operations_pb2.py (2 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/events_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/events_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/genesis_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/genesis_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/types_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/interchain_security/v1/types_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/module/v1/module_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/module/v1/module_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/events_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/events_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/types_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/types_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/events_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/events_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/genesis_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/genesis_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/query_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/tx_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/types_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/core/v1/types_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/module/v1/module_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/module/v1/module_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/events_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/events_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/genesis_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/genesis_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/query_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/tx_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/tx_pb2_grpc.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/types_pb2.py (1 hunks)
  • pyinjective/proto/hyperlane/warp/v1/types_pb2_grpc.py (1 hunks)
  • pyinjective/proto/injective/exchange/v1beta1/exchange_pb2.py (4 hunks)
  • pyinjective/proto/injective/exchange/v1beta1/query_pb2_grpc.py (1 hunks)
  • pyinjective/proto/injective/exchange/v1beta1/tx_pb2.py (4 hunks)
  • pyinjective/proto/injective/exchange/v1beta1/tx_pb2_grpc.py (0 hunks)
  • pyinjective/proto/injective/exchange/v2/events_pb2.py (2 hunks)
  • pyinjective/proto/injective/exchange/v2/exchange_pb2.py (2 hunks)
  • pyinjective/proto/injective/exchange/v2/genesis_pb2.py (3 hunks)
  • pyinjective/proto/injective/exchange/v2/market_pb2.py (4 hunks)
  • pyinjective/proto/injective/exchange/v2/proposal_pb2.py (7 hunks)
  • pyinjective/proto/injective/exchange/v2/query_pb2_grpc.py (12 hunks)
  • pyinjective/proto/injective/exchange/v2/tx_pb2_grpc.py (4 hunks)
  • pyinjective/proto/injective/peggy/v1/events_pb2.py (3 hunks)
  • pyinjective/proto/injective/peggy/v1/genesis_pb2.py (2 hunks)
  • pyinjective/proto/injective/peggy/v1/msgs_pb2.py (3 hunks)
  • pyinjective/proto/injective/peggy/v1/msgs_pb2_grpc.py (4 hunks)
  • pyinjective/proto/injective/peggy/v1/rate_limit_pb2.py (1 hunks)
  • pyinjective/proto/injective/peggy/v1/rate_limit_pb2_grpc.py (1 hunks)
  • pyinjective/proto/injective/stream/v2/query_pb2.py (3 hunks)
  • tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (4 hunks)
  • tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py (18 hunks)
  • tests/client/chain/stream_grpc/test_chain_grpc_chain_stream.py (5 hunks)
  • tests/test_async_client_v2_deprecation_warnings.py (1 hunks)
  • tests/test_composer_v2.py (18 hunks)
💤 Files with no reviewable changes (1)
  • pyinjective/proto/injective/exchange/v1beta1/tx_pb2_grpc.py
✅ Files skipped from review due to trivial changes (3)
  • pyinjective/proto/hyperlane/core/v1/types_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/types_pb2.py
  • pyinjective/proto/injective/peggy/v1/rate_limit_pb2_grpc.py
🚧 Files skipped from review as they are similar to previous changes (25)
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/types_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/module/v1/module_pb2_grpc.py
  • buf.gen.yaml
  • pyinjective/proto/hyperlane/core/interchain_security/v1/genesis_pb2.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2_grpc.py
  • tests/test_async_client_v2_deprecation_warnings.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/events_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/v1/types_pb2.py
  • pyinjective/proto/injective/exchange/v1beta1/exchange_pb2.py
  • examples/chain_client/7_ChainStream.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/events_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/v1/genesis_pb2_grpc.py
  • pyinjective/proto/injective/peggy/v1/rate_limit_pb2.py
  • pyinjective/proto/hyperlane/warp/module/v1/module_pb2.py
  • pyinjective/proto/hyperlane/core/v1/genesis_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/types_pb2_grpc.py
  • examples/chain_client/exchange/query/66_OpenInterest.py
  • pyinjective/proto/hyperlane/warp/v1/events_pb2_grpc.py
  • pyinjective/client/chain/grpc_stream/chain_grpc_chain_stream.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/genesis_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/module/v1/module_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/genesis_pb2_grpc.py
  • pyinjective/proto/injective/exchange/v1beta1/query_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/events_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/types_pb2.py
🧰 Additional context used
🧬 Code graph analysis (24)
examples/chain_client/exchange/30_MsgOffsetPosition.py (5)
pyinjective/async_client_v2.py (5)
  • AsyncClient (54-1524)
  • initialize_tokens_from_chain_denoms (1286-1329)
  • composer (1267-1270)
  • current_chain_gas_price (1272-1284)
  • fetch_account (228-243)
pyinjective/core/broadcaster.py (2)
  • MsgBroadcasterWithPk (64-402)
  • new_using_simulation (82-113)
pyinjective/core/network.py (2)
  • Network (105-378)
  • testnet (165-219)
pyinjective/wallet.py (5)
  • PrivateKey (28-103)
  • from_hex (73-76)
  • to_public_key (84-92)
  • to_address (175-181)
  • get_subaccount_id (263-266)
pyinjective/composer_v2.py (1)
  • msg_offset_position (1210-1218)
examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py (2)
pyinjective/composer_v2.py (2)
  • open_notional_cap (1220-1226)
  • uncapped_open_notional_cap (1228-1229)
pyinjective/async_client_v2.py (1)
  • composer (1267-1270)
examples/chain_client/exchange/9_MsgBatchUpdateOrders.py (1)
pyinjective/composer_v2.py (4)
  • derivative_order (403-427)
  • calculate_margin (393-401)
  • spot_order (360-391)
  • msg_batch_update_orders (757-789)
tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (1)
pyinjective/proto/injective/exchange/v2/query_pb2_grpc.py (6)
  • AuctionExchangeTransferDenomDecimal (432-437)
  • AuctionExchangeTransferDenomDecimal (1468-1492)
  • AuctionExchangeTransferDenomDecimals (439-445)
  • AuctionExchangeTransferDenomDecimals (1495-1519)
  • OpenInterest (835-840)
  • OpenInterest (3007-3031)
pyinjective/async_client_v2.py (1)
pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (3)
  • fetch_auction_exchange_transfer_denom_decimal (90-94)
  • fetch_auction_exchange_transfer_denom_decimals (96-102)
  • fetch_open_interest (656-660)
examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py (3)
pyinjective/composer_v2.py (2)
  • open_notional_cap (1220-1226)
  • uncapped_open_notional_cap (1228-1229)
pyinjective/async_client_v2.py (1)
  • composer (1267-1270)
pyinjective/async_client.py (1)
  • composer (2222-2229)
examples/chain_client/exchange/25_MsgUpdateDerivativeMarket.py (3)
pyinjective/async_client_v2.py (1)
  • composer (1267-1270)
pyinjective/async_client.py (1)
  • composer (2222-2229)
pyinjective/composer_v2.py (1)
  • uncapped_open_notional_cap (1228-1229)
pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (3)
pyinjective/async_client_v2.py (3)
  • fetch_auction_exchange_transfer_denom_decimal (444-445)
  • fetch_auction_exchange_transfer_denom_decimals (447-450)
  • fetch_open_interest (845-846)
tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (3)
  • AuctionExchangeTransferDenomDecimal (120-123)
  • AuctionExchangeTransferDenomDecimals (125-128)
  • OpenInterest (394-395)
pyinjective/proto/injective/exchange/v2/query_pb2_grpc.py (6)
  • AuctionExchangeTransferDenomDecimal (432-437)
  • AuctionExchangeTransferDenomDecimal (1468-1492)
  • AuctionExchangeTransferDenomDecimals (439-445)
  • AuctionExchangeTransferDenomDecimals (1495-1519)
  • OpenInterest (835-840)
  • OpenInterest (3007-3031)
examples/chain_client/exchange/query/9_AuctionExchangeTransferDenomDecimals.py (2)
pyinjective/async_client_v2.py (1)
  • fetch_auction_exchange_transfer_denom_decimals (447-450)
pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (1)
  • fetch_auction_exchange_transfer_denom_decimals (96-102)
examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py (2)
pyinjective/composer_v2.py (2)
  • open_notional_cap (1220-1226)
  • uncapped_open_notional_cap (1228-1229)
pyinjective/async_client_v2.py (1)
  • composer (1267-1270)
tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py (3)
pyinjective/async_client_v2.py (3)
  • fetch_auction_exchange_transfer_denom_decimal (444-445)
  • fetch_auction_exchange_transfer_denom_decimals (447-450)
  • fetch_open_interest (845-846)
pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (3)
  • fetch_auction_exchange_transfer_denom_decimal (90-94)
  • fetch_auction_exchange_transfer_denom_decimals (96-102)
  • fetch_open_interest (656-660)
tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (1)
  • OpenInterest (394-395)
pyinjective/proto/injective/exchange/v2/query_pb2_grpc.py (1)
tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py (3)
  • AuctionExchangeTransferDenomDecimal (120-123)
  • AuctionExchangeTransferDenomDecimals (125-128)
  • OpenInterest (394-395)
pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py (1)
pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py (4)
  • MsgStub (8-57)
  • MsgServicer (60-118)
  • add_MsgServicer_to_server (121-167)
  • Msg (171-389)
tests/test_composer_v2.py (2)
pyinjective/composer_v2.py (14)
  • open_notional_cap (1220-1226)
  • spot_order (360-391)
  • derivative_order (403-427)
  • binary_options_order (429-453)
  • uncapped_open_notional_cap (1228-1229)
  • chain_stream_bank_balances_filter (1532-1536)
  • chain_stream_subaccount_deposits_filter (1538-1543)
  • chain_stream_trades_filter (1545-1552)
  • chain_stream_orders_filter (1554-1561)
  • chain_stream_orderbooks_filter (1563-1568)
  • chain_stream_positions_filter (1570-1577)
  • chain_stream_oracle_price_filter (1579-1584)
  • chain_stream_order_failures_filter (1586-1591)
  • chain_stream_conditional_order_trigger_failures_filter (1593-1602)
pyinjective/core/token.py (1)
  • convert_value_to_extended_decimal_format (19-20)
examples/chain_client/exchange/query/8_AuctionExchangeTransferDenomDecimal.py (2)
pyinjective/async_client_v2.py (1)
  • fetch_auction_exchange_transfer_denom_decimal (444-445)
pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py (1)
  • fetch_auction_exchange_transfer_denom_decimal (90-94)
pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py (2)
pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py (4)
  • QueryStub (8-37)
  • QueryServicer (40-70)
  • add_QueryServicer_to_server (73-99)
  • Query (103-213)
pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py (4)
  • QueryStub (8-57)
  • QueryServicer (60-122)
  • add_QueryServicer_to_server (125-171)
  • Query (175-393)
tests/client/chain/stream_grpc/test_chain_grpc_chain_stream.py (2)
pyinjective/async_client_v2.py (1)
  • composer (1267-1270)
pyinjective/composer_v2.py (2)
  • chain_stream_order_failures_filter (1586-1591)
  • chain_stream_conditional_order_trigger_failures_filter (1593-1602)
pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py (1)
pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py (4)
  • QueryStub (8-37)
  • QueryServicer (40-70)
  • add_QueryServicer_to_server (73-99)
  • Query (103-213)
pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py (1)
pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py (4)
  • QueryStub (8-57)
  • QueryServicer (60-122)
  • add_QueryServicer_to_server (125-171)
  • Query (175-393)
pyinjective/composer_v2.py (1)
pyinjective/core/token.py (1)
  • convert_value_to_extended_decimal_format (19-20)
pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2_grpc.py (2)
pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py (4)
  • QueryStub (8-37)
  • QueryServicer (40-70)
  • add_QueryServicer_to_server (73-99)
  • Query (103-213)
pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py (4)
  • QueryStub (8-57)
  • QueryServicer (60-122)
  • add_QueryServicer_to_server (125-171)
  • Query (175-393)
pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2_grpc.py (3)
pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py (4)
  • MsgStub (8-57)
  • MsgServicer (60-118)
  • add_MsgServicer_to_server (121-167)
  • Msg (171-389)
pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py (4)
  • MsgStub (8-32)
  • MsgServicer (35-58)
  • add_MsgServicer_to_server (61-82)
  • Msg (86-169)
pyinjective/proto/hyperlane/warp/v1/tx_pb2_grpc.py (4)
  • MsgStub (8-52)
  • MsgServicer (55-106)
  • add_MsgServicer_to_server (109-150)
  • Msg (154-345)
pyinjective/proto/hyperlane/warp/v1/tx_pb2_grpc.py (1)
pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py (4)
  • MsgStub (8-32)
  • MsgServicer (35-58)
  • add_MsgServicer_to_server (61-82)
  • Msg (86-169)
pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py (1)
pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py (4)
  • MsgStub (8-32)
  • MsgServicer (35-58)
  • add_MsgServicer_to_server (61-82)
  • Msg (86-169)
🪛 Gitleaks (8.28.0)
tests/test_composer_v2.py

[high] 2345-2345: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 2576-2576: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 Ruff (0.14.1)
examples/chain_client/exchange/9_MsgBatchUpdateOrders.py

113-113: Decimal() called with float literal argument

Replace with string literal

(RUF032)


115-115: Decimal() called with float literal argument

Replace with string literal

(RUF032)

tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py

121-121: Unused method argument: request

(ARG002)


121-121: Unused method argument: context

(ARG002)


121-121: Unused method argument: metadata

(ARG002)


126-126: Unused method argument: request

(ARG002)


126-126: Unused method argument: context

(ARG002)


126-126: Unused method argument: metadata

(ARG002)


394-394: Unused method argument: request

(ARG002)


394-394: Unused method argument: context

(ARG002)


394-394: Unused method argument: metadata

(ARG002)

pyinjective/proto/exchange/injective_archiver_rpc_pb2_grpc.py

149-149: Unused method argument: request

(ARG002)

pyinjective/proto/injective/exchange/v2/query_pb2_grpc.py

432-432: Unused method argument: request

(ARG002)


439-439: Unused method argument: request

(ARG002)


835-835: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py

39-39: Unused method argument: request

(ARG002)


46-46: Unused method argument: request

(ARG002)


53-53: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py

49-49: Unused method argument: request

(ARG002)


56-56: Unused method argument: request

(ARG002)


63-63: Unused method argument: request

(ARG002)


70-70: Unused method argument: request

(ARG002)


77-77: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py

64-64: Unused method argument: request

(ARG002)


71-71: Unused method argument: request

(ARG002)


78-78: Unused method argument: request

(ARG002)


85-85: Unused method argument: request

(ARG002)


96-96: Unused method argument: request

(ARG002)


103-103: Unused method argument: request

(ARG002)


110-110: Unused method argument: request

(ARG002)


117-117: Unused method argument: request

(ARG002)

pyinjective/proto/injective/peggy/v1/msgs_pb2_grpc.py

194-194: Unused method argument: request

(ARG002)


202-202: Unused method argument: request

(ARG002)


210-210: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py

44-44: Unused method argument: request

(ARG002)


51-51: Unused method argument: request

(ARG002)


58-58: Unused method argument: request

(ARG002)


65-65: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2_grpc.py

64-64: Unused method argument: request

(ARG002)


71-71: Unused method argument: request

(ARG002)


78-78: Unused method argument: request

(ARG002)


85-85: Unused method argument: request

(ARG002)


92-92: Unused method argument: request

(ARG002)


99-99: Unused method argument: request

(ARG002)


106-106: Unused method argument: request

(ARG002)


113-113: Unused method argument: request

(ARG002)

pyinjective/proto/injective/exchange/v2/tx_pb2_grpc.py

490-490: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2_grpc.py

59-59: Unused method argument: request

(ARG002)


66-66: Unused method argument: request

(ARG002)


73-73: Unused method argument: request

(ARG002)


80-80: Unused method argument: request

(ARG002)


87-87: Unused method argument: request

(ARG002)


94-94: Unused method argument: request

(ARG002)


101-101: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/warp/v1/tx_pb2_grpc.py

59-59: Unused method argument: request

(ARG002)


66-66: Unused method argument: request

(ARG002)


73-73: Unused method argument: request

(ARG002)


80-80: Unused method argument: request

(ARG002)


87-87: Unused method argument: request

(ARG002)


94-94: Unused method argument: request

(ARG002)


101-101: Unused method argument: request

(ARG002)

pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py

64-64: Unused method argument: request

(ARG002)


71-71: Unused method argument: request

(ARG002)


78-78: Unused method argument: request

(ARG002)


85-85: Unused method argument: request

(ARG002)


92-92: Unused method argument: request

(ARG002)


99-99: Unused method argument: request

(ARG002)


106-106: Unused method argument: request

(ARG002)


113-113: Unused method argument: request

(ARG002)

Comment on lines 21 to 23
define clean_repos
rm -Rf cosmos-sdk
rm -Rf ibc-go
rm -Rf cometbft
rm -Rf wasmd
rm -Rf injective-core
rm -Rf injective-indexer
endef
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 | 🔴 Critical

🧩 Analysis chain

Verify that cleanup consolidation doesn't break the build workflow.

The removal of cosmos-sdk, ibc-go, cometbft, wasmd, and injective-core from clean_repos appears intentional, given that clone-all now only clones injective-indexer. However, confirm that:

  1. All necessary proto dependencies are now available in injective-indexer v1.17.0-beta
  2. No other build targets or workflows reference the removed repositories
  3. buf.gen.yaml does not reference the removed repos

🏁 Script executed:

#!/bin/bash
# Verify that buf.gen.yaml and the build process don't reference removed repos

echo "=== Checking buf.gen.yaml for references to removed repos ==="
if [ -f buf.gen.yaml ]; then
  grep -i "cosmos-sdk\|ibc-go\|cometbft\|wasmd" buf.gen.yaml || echo "No references found (OK)"
else
  echo "buf.gen.yaml not found"
fi

echo ""
echo "=== Checking for any clone targets for removed repos in Makefile ==="
grep -n "clone-" Makefile | grep -v "clone-all\|clone-injective-indexer" || echo "No other clone targets found (OK)"

echo ""
echo "=== Checking for any references to removed repos in Makefile ==="
grep -i "cosmos-sdk\|ibc-go\|cometbft\|wasmd\|injective-core" Makefile || echo "No references found (OK)"

Length of output: 618


I found a critical inconsistency. Let me verify the build process to confirm the impact.

Now let me verify how the build process uses buf.gen.yaml:

Let me search the Makefile for how proto generation is invoked:These results don't show how the specific repository uses buf.gen.yaml in the Makefile. Let me search the Makefile more directly for the actual proto target:

[/run_scripts]


🏁 Script executed:

#!/bin/bash
# Look for proto, gen, or buf references in Makefile

echo "=== Full Makefile content (first 50 lines) ==="
head -n 50 Makefile

echo ""
echo "=== Lines mentioning proto, gen, buf, or pb ==="
grep -n -i "proto\|gen\|buf\|\.pb" Makefile || echo "No matches found"

echo ""
echo "=== Looking for all targets in Makefile ==="
grep -n "^[a-z-]*:" Makefile | head -20

Length of output: 2412


buf.gen.yaml still references removed repositories—this will break the build.

The Makefile cleanup removes cloning of cosmos-sdk, ibc-go, cometbft, and wasmd, but buf.gen.yaml (line 7, invoked via buf generate --template buf.gen.yaml) still contains active git_repo entries for these same repositories:

  • https://github.com/InjectiveLabs/ibc-go
  • https://github.com/InjectiveLabs/wasmd
  • https://github.com/InjectiveLabs/cometbft
  • https://github.com/InjectiveLabs/cosmos-sdk

Additionally, PROTO_MODULES (line 12) still references modules corresponding to these removed repos (cometbft, ibc, cosmos, tendermint).

Either:

  1. Update buf.gen.yaml to remove the git_repo entries for these repositories, OR
  2. Verify that injective-indexer v1.17.0-beta bundles all necessary proto files and update buf.gen.yaml accordingly
🤖 Prompt for AI Agents
In Makefile around lines 21 to 23, the cleanup target removes cloning of
external repos but buf.gen.yaml (used by buf generate at line 7) still
references git_repo entries for cosmos-sdk, ibc-go, cometbft and wasmd and
PROTO_MODULES still lists modules from those repos; update buf.gen.yaml to
either remove those git_repo entries and modules or replace them with the
bundled injective-indexer v1.17.0-beta proto sources if that bundle truly
contains all required proto files—verify bundle completeness, then remove the
obsolete git_repo entries and corresponding PROTO_MODULES or update them to
point to the bundled module names so buf generate no longer expects the removed
repositories.

"""Client and server classes corresponding to protobuf-defined services."""
import grpc

from hyperlane.core.interchain_security.v1 import tx_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2
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 | 🔴 Critical

Broken import path: use repo package root (pyinjective.proto.hyperlane...).

from hyperlane.core.interchain_security.v1 import tx_pb2 ... will fail unless hyperlane is a top-level package. Other modules in this repo import via pyinjective.proto.*. Fix the import (or regenerate with correct python_package) to avoid runtime import errors.

-from hyperlane.core.interchain_security.v1 import tx_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2
+from pyinjective.proto.hyperlane.core.interchain_security.v1 import tx_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2
📝 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
from hyperlane.core.interchain_security.v1 import tx_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2
from pyinjective.proto.hyperlane.core.interchain_security.v1 import tx_pb2 as hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2
🤖 Prompt for AI Agents
In pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py around
line 5, the import uses a top-level package path ("from
hyperlane.core.interchain_security.v1 import tx_pb2 ...") which will fail;
replace it with the repo-root package path ("from
pyinjective.proto.hyperlane.core.interchain_security.v1 import tx_pb2 as ...")
or regenerate the gRPC stubs with the correct python_package option so all
imports use pyinjective.proto.*, and ensure any other imports in this file are
similarly updated to the pyinjective.proto.* namespace.

Comment on lines +121 to +168
def add_MsgServicer_to_server(servicer, server):
rpc_method_handlers = {
'CreateMessageIdMultisigIsm': grpc.unary_unary_rpc_method_handler(
servicer.CreateMessageIdMultisigIsm,
request_deserializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgCreateMessageIdMultisigIsm.FromString,
response_serializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgCreateMessageIdMultisigIsmResponse.SerializeToString,
),
'CreateMerkleRootMultisigIsm': grpc.unary_unary_rpc_method_handler(
servicer.CreateMerkleRootMultisigIsm,
request_deserializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgCreateMerkleRootMultisigIsm.FromString,
response_serializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgCreateMerkleRootMultisigIsmResponse.SerializeToString,
),
'CreateNoopIsm': grpc.unary_unary_rpc_method_handler(
servicer.CreateNoopIsm,
request_deserializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgCreateNoopIsm.FromString,
response_serializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgCreateNoopIsmResponse.SerializeToString,
),
'CreateRoutingIsm': grpc.unary_unary_rpc_method_handler(
servicer.CreateRoutingIsm,
request_deserializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgCreateRoutingIsm.FromString,
response_serializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgCreateRoutingIsmResponse.SerializeToString,
),
'SetRoutingIsmDomain': grpc.unary_unary_rpc_method_handler(
servicer.SetRoutingIsmDomain,
request_deserializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgSetRoutingIsmDomain.FromString,
response_serializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgSetRoutingIsmDomainResponse.SerializeToString,
),
'RemoveRoutingIsmDomain': grpc.unary_unary_rpc_method_handler(
servicer.RemoveRoutingIsmDomain,
request_deserializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgRemoveRoutingIsmDomain.FromString,
response_serializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgRemoveRoutingIsmDomainResponse.SerializeToString,
),
'UpdateRoutingIsmOwner': grpc.unary_unary_rpc_method_handler(
servicer.UpdateRoutingIsmOwner,
request_deserializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgUpdateRoutingIsmOwner.FromString,
response_serializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgUpdateRoutingIsmOwnerResponse.SerializeToString,
),
'AnnounceValidator': grpc.unary_unary_rpc_method_handler(
servicer.AnnounceValidator,
request_deserializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgAnnounceValidator.FromString,
response_serializer=hyperlane_dot_core_dot_interchain__security_dot_v1_dot_tx__pb2.MsgAnnounceValidatorResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'hyperlane.core.interchain_security.v1.Msg', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
server.add_registered_method_handlers('hyperlane.core.interchain_security.v1.Msg', rpc_method_handlers)

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 | 🔴 Critical

🧩 Analysis chain

Confirm grpc runtime compatibility with generated stubs.

This file relies on _registered_method=True and server.add_registered_method_handlers, which require a sufficiently new grpcio. Ensure the repo pins compatible versions of grpcio, grpcio-tools, and protobuf.


🏁 Script executed:

#!/bin/bash
# Inspect pinned versions to confirm compatibility with generated code.
rg -nP 'grpcio(-tools)?\s*[=><!]+' -g '*requirements*' -g 'pyproject.toml' -g 'setup.cfg' -g 'setup.py'
rg -nP 'protobuf\s*[=><!]+' -g '*requirements*' -g 'pyproject.toml' -g 'setup.cfg' -g 'setup.py'

Length of output: 106


#!/bin/bash
# Check if the generated file includes version checking logic
head -50 pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py | grep -A 10 -i "version\|grpc\|import"

🏁 Script executed:

#!/bin/bash
# Check if the generated file includes version checking logic
head -50 pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py

Length of output: 3577


🏁 Script executed:

#!/bin/bash
# Search entire file for version checking or GRPC_GENERATED_VERSION
grep -n "GRPC_GENERATED_VERSION\|__version__\|grpcio.*[0-9]" pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py | head -20

Length of output: 0


Pin grpcio and grpcio-tools to minimum compatible versions.

The generated stubs use _registered_method=True and server.add_registered_method_handlers(), which require grpcio ≥ 1.64.0. Update pyproject.toml to replace grpcio = "*" and grpcio-tools = "*" with pinned minimum versions (e.g., grpcio = "^1.66.0") to prevent runtime errors on older grpcio installations.

Comment on lines +1 to +113
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: hyperlane/core/post_dispatch/v1/tx.proto
# Protobuf Python Version: 5.26.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)

_sym_db = _symbol_database.Default()


from pyinjective.proto.cosmos.msg.v1 import msg_pb2 as cosmos_dot_msg_dot_v1_dot_msg__pb2
from pyinjective.proto.amino import amino_pb2 as amino_dot_amino__pb2
from pyinjective.proto.cosmos_proto import cosmos_pb2 as cosmos__proto_dot_cosmos__pb2
from pyinjective.proto.gogoproto import gogo_pb2 as gogoproto_dot_gogo__pb2
from hyperlane.core.post_dispatch.v1 import types_pb2 as hyperlane_dot_core_dot_post__dispatch_dot_v1_dot_types__pb2
from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as cosmos_dot_base_dot_v1beta1_dot_coin__pb2


DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n(hyperlane/core/post_dispatch/v1/tx.proto\x12\x1fhyperlane.core.post_dispatch.v1\x1a\x17\x63osmos/msg/v1/msg.proto\x1a\x11\x61mino/amino.proto\x1a\x19\x63osmos_proto/cosmos.proto\x1a\x14gogoproto/gogo.proto\x1a+hyperlane/core/post_dispatch/v1/types.proto\x1a\x1e\x63osmos/base/v1beta1/coin.proto\"\x91\x01\n\x0cMsgCreateIgp\x12.\n\x05owner\x18\x01 \x01(\tB\x18\xd2\xb4-\x14\x63osmos.AddressStringR\x05owner\x12\x14\n\x05\x64\x65nom\x18\x02 \x01(\tR\x05\x64\x65nom:;\x82\xe7\xb0*\x05owner\x8a\xe7\xb0*,hyperlane/v1/MsgCreateInterchainGasPaymaster\"k\n\x14MsgCreateIgpResponse\x12S\n\x02id\x18\x01 \x01(\tBC\xc8\xde\x1f\x00\xda\xde\x1f;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddressR\x02id\"\x94\x02\n\x0eMsgSetIgpOwner\x12.\n\x05owner\x18\x01 \x01(\tB\x18\xd2\xb4-\x14\x63osmos.AddressStringR\x05owner\x12Z\n\x06igp_id\x18\x02 \x01(\tBC\xc8\xde\x1f\x00\xda\xde\x1f;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddressR\x05igpId\x12\x1b\n\tnew_owner\x18\x03 \x01(\tR\x08newOwner\x12-\n\x12renounce_ownership\x18\x04 \x01(\x08R\x11renounceOwnership:*\x82\xe7\xb0*\x05owner\x8a\xe7\xb0*\x1bhyperlane/v1/MsgSetIgpOwner\"\x18\n\x16MsgSetIgpOwnerResponse\"\xcd\x02\n\x1aMsgSetDestinationGasConfig\x12.\n\x05owner\x18\x01 \x01(\tB\x18\xd2\xb4-\x14\x63osmos.AddressStringR\x05owner\x12Z\n\x06igp_id\x18\x02 \x01(\tBC\xc8\xde\x1f\x00\xda\xde\x1f;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddressR\x05igpId\x12k\n\x16\x64\x65stination_gas_config\x18\x03 \x01(\x0b\x32\x35.hyperlane.core.post_dispatch.v1.DestinationGasConfigR\x14\x64\x65stinationGasConfig:6\x82\xe7\xb0*\x05owner\x8a\xe7\xb0*\'hyperlane/v1/MsgSetDestinationGasConfig\"$\n\"MsgSetDestinationGasConfigResponse\"\xd4\x03\n\x0cMsgPayForGas\x12\x30\n\x06sender\x18\x01 \x01(\tB\x18\xd2\xb4-\x14\x63osmos.AddressStringR\x06sender\x12Z\n\x06igp_id\x18\x02 \x01(\tBC\xc8\xde\x1f\x00\xda\xde\x1f;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddressR\x05igpId\x12\x62\n\nmessage_id\x18\x03 \x01(\tBC\xc8\xde\x1f\x00\xda\xde\x1f;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddressR\tmessageId\x12-\n\x12\x64\x65stination_domain\x18\x04 \x01(\rR\x11\x64\x65stinationDomain\x12:\n\tgas_limit\x18\x05 \x01(\tB\x1d\xc8\xde\x1f\x00\xda\xde\x1f\x15\x63osmossdk.io/math.IntR\x08gasLimit\x12<\n\x06\x61mount\x18\x06 \x01(\x0b\x32\x19.cosmos.base.v1beta1.CoinB\t\xc8\xde\x1f\x00\xa8\xe7\xb0*\x01R\x06\x61mount:)\x82\xe7\xb0*\x06sender\x8a\xe7\xb0*\x19hyperlane/v1/MsgPayForGas\"\x16\n\x14MsgPayForGasResponse\"\xbf\x01\n\x08MsgClaim\x12\x30\n\x06sender\x18\x01 \x01(\tB\x18\xd2\xb4-\x14\x63osmos.AddressStringR\x06sender\x12Z\n\x06igp_id\x18\x02 \x01(\tBC\xc8\xde\x1f\x00\xda\xde\x1f;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddressR\x05igpId:%\x82\xe7\xb0*\x06sender\x8a\xe7\xb0*\x15hyperlane/v1/MsgClaim\"\x12\n\x10MsgClaimResponse\"\xe2\x01\n\x17MsgCreateMerkleTreeHook\x12.\n\x05owner\x18\x01 \x01(\tB\x18\xd2\xb4-\x14\x63osmos.AddressStringR\x05owner\x12\x62\n\nmailbox_id\x18\x02 \x01(\tBC\xc8\xde\x1f\x00\xda\xde\x1f;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddressR\tmailboxId:3\x82\xe7\xb0*\x05owner\x8a\xe7\xb0*$hyperlane/v1/MsgCreateMerkleTreeHook\"v\n\x1fMsgCreateMerkleTreeHookResponse\x12S\n\x02id\x18\x01 \x01(\tBC\xc8\xde\x1f\x00\xda\xde\x1f;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddressR\x02id\"x\n\x11MsgCreateNoopHook\x12.\n\x05owner\x18\x01 \x01(\tB\x18\xd2\xb4-\x14\x63osmos.AddressStringR\x05owner:3\x82\xe7\xb0*\x05owner\x8a\xe7\xb0*$hyperlane/v1/MsgCreateMerkleTreeHook\"p\n\x19MsgCreateNoopHookResponse\x12S\n\x02id\x18\x01 \x01(\tBC\xc8\xde\x1f\x00\xda\xde\x1f;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddressR\x02id2\x88\x07\n\x03Msg\x12q\n\tCreateIgp\x12-.hyperlane.core.post_dispatch.v1.MsgCreateIgp\x1a\x35.hyperlane.core.post_dispatch.v1.MsgCreateIgpResponse\x12w\n\x0bSetIgpOwner\x12/.hyperlane.core.post_dispatch.v1.MsgSetIgpOwner\x1a\x37.hyperlane.core.post_dispatch.v1.MsgSetIgpOwnerResponse\x12\x9b\x01\n\x17SetDestinationGasConfig\x12;.hyperlane.core.post_dispatch.v1.MsgSetDestinationGasConfig\x1a\x43.hyperlane.core.post_dispatch.v1.MsgSetDestinationGasConfigResponse\x12q\n\tPayForGas\x12-.hyperlane.core.post_dispatch.v1.MsgPayForGas\x1a\x35.hyperlane.core.post_dispatch.v1.MsgPayForGasResponse\x12\x65\n\x05\x43laim\x12).hyperlane.core.post_dispatch.v1.MsgClaim\x1a\x31.hyperlane.core.post_dispatch.v1.MsgClaimResponse\x12\x92\x01\n\x14\x43reateMerkleTreeHook\x12\x38.hyperlane.core.post_dispatch.v1.MsgCreateMerkleTreeHook\x1a@.hyperlane.core.post_dispatch.v1.MsgCreateMerkleTreeHookResponse\x12\x80\x01\n\x0e\x43reateNoopHook\x12\x32.hyperlane.core.post_dispatch.v1.MsgCreateNoopHook\x1a:.hyperlane.core.post_dispatch.v1.MsgCreateNoopHookResponse\x1a\x05\x80\xe7\xb0*\x01\x42\x94\x02\n#com.hyperlane.core.post_dispatch.v1B\x07TxProtoP\x01ZIgithub.com/bcp-innovations/hyperlane-cosmos/x/core/02_post_dispatch/types\xa2\x02\x03HCP\xaa\x02\x1eHyperlane.Core.PostDispatch.V1\xca\x02\x1eHyperlane\\Core\\PostDispatch\\V1\xe2\x02*Hyperlane\\Core\\PostDispatch\\V1\\GPBMetadata\xea\x02!Hyperlane::Core::PostDispatch::V1b\x06proto3')

_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'hyperlane.core.post_dispatch.v1.tx_pb2', _globals)
if not _descriptor._USE_C_DESCRIPTORS:
_globals['DESCRIPTOR']._loaded_options = None
_globals['DESCRIPTOR']._serialized_options = b'\n#com.hyperlane.core.post_dispatch.v1B\007TxProtoP\001ZIgithub.com/bcp-innovations/hyperlane-cosmos/x/core/02_post_dispatch/types\242\002\003HCP\252\002\036Hyperlane.Core.PostDispatch.V1\312\002\036Hyperlane\\Core\\PostDispatch\\V1\342\002*Hyperlane\\Core\\PostDispatch\\V1\\GPBMetadata\352\002!Hyperlane::Core::PostDispatch::V1'
_globals['_MSGCREATEIGP'].fields_by_name['owner']._loaded_options = None
_globals['_MSGCREATEIGP'].fields_by_name['owner']._serialized_options = b'\322\264-\024cosmos.AddressString'
_globals['_MSGCREATEIGP']._loaded_options = None
_globals['_MSGCREATEIGP']._serialized_options = b'\202\347\260*\005owner\212\347\260*,hyperlane/v1/MsgCreateInterchainGasPaymaster'
_globals['_MSGCREATEIGPRESPONSE'].fields_by_name['id']._loaded_options = None
_globals['_MSGCREATEIGPRESPONSE'].fields_by_name['id']._serialized_options = b'\310\336\037\000\332\336\037;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddress'
_globals['_MSGSETIGPOWNER'].fields_by_name['owner']._loaded_options = None
_globals['_MSGSETIGPOWNER'].fields_by_name['owner']._serialized_options = b'\322\264-\024cosmos.AddressString'
_globals['_MSGSETIGPOWNER'].fields_by_name['igp_id']._loaded_options = None
_globals['_MSGSETIGPOWNER'].fields_by_name['igp_id']._serialized_options = b'\310\336\037\000\332\336\037;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddress'
_globals['_MSGSETIGPOWNER']._loaded_options = None
_globals['_MSGSETIGPOWNER']._serialized_options = b'\202\347\260*\005owner\212\347\260*\033hyperlane/v1/MsgSetIgpOwner'
_globals['_MSGSETDESTINATIONGASCONFIG'].fields_by_name['owner']._loaded_options = None
_globals['_MSGSETDESTINATIONGASCONFIG'].fields_by_name['owner']._serialized_options = b'\322\264-\024cosmos.AddressString'
_globals['_MSGSETDESTINATIONGASCONFIG'].fields_by_name['igp_id']._loaded_options = None
_globals['_MSGSETDESTINATIONGASCONFIG'].fields_by_name['igp_id']._serialized_options = b'\310\336\037\000\332\336\037;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddress'
_globals['_MSGSETDESTINATIONGASCONFIG']._loaded_options = None
_globals['_MSGSETDESTINATIONGASCONFIG']._serialized_options = b'\202\347\260*\005owner\212\347\260*\'hyperlane/v1/MsgSetDestinationGasConfig'
_globals['_MSGPAYFORGAS'].fields_by_name['sender']._loaded_options = None
_globals['_MSGPAYFORGAS'].fields_by_name['sender']._serialized_options = b'\322\264-\024cosmos.AddressString'
_globals['_MSGPAYFORGAS'].fields_by_name['igp_id']._loaded_options = None
_globals['_MSGPAYFORGAS'].fields_by_name['igp_id']._serialized_options = b'\310\336\037\000\332\336\037;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddress'
_globals['_MSGPAYFORGAS'].fields_by_name['message_id']._loaded_options = None
_globals['_MSGPAYFORGAS'].fields_by_name['message_id']._serialized_options = b'\310\336\037\000\332\336\037;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddress'
_globals['_MSGPAYFORGAS'].fields_by_name['gas_limit']._loaded_options = None
_globals['_MSGPAYFORGAS'].fields_by_name['gas_limit']._serialized_options = b'\310\336\037\000\332\336\037\025cosmossdk.io/math.Int'
_globals['_MSGPAYFORGAS'].fields_by_name['amount']._loaded_options = None
_globals['_MSGPAYFORGAS'].fields_by_name['amount']._serialized_options = b'\310\336\037\000\250\347\260*\001'
_globals['_MSGPAYFORGAS']._loaded_options = None
_globals['_MSGPAYFORGAS']._serialized_options = b'\202\347\260*\006sender\212\347\260*\031hyperlane/v1/MsgPayForGas'
_globals['_MSGCLAIM'].fields_by_name['sender']._loaded_options = None
_globals['_MSGCLAIM'].fields_by_name['sender']._serialized_options = b'\322\264-\024cosmos.AddressString'
_globals['_MSGCLAIM'].fields_by_name['igp_id']._loaded_options = None
_globals['_MSGCLAIM'].fields_by_name['igp_id']._serialized_options = b'\310\336\037\000\332\336\037;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddress'
_globals['_MSGCLAIM']._loaded_options = None
_globals['_MSGCLAIM']._serialized_options = b'\202\347\260*\006sender\212\347\260*\025hyperlane/v1/MsgClaim'
_globals['_MSGCREATEMERKLETREEHOOK'].fields_by_name['owner']._loaded_options = None
_globals['_MSGCREATEMERKLETREEHOOK'].fields_by_name['owner']._serialized_options = b'\322\264-\024cosmos.AddressString'
_globals['_MSGCREATEMERKLETREEHOOK'].fields_by_name['mailbox_id']._loaded_options = None
_globals['_MSGCREATEMERKLETREEHOOK'].fields_by_name['mailbox_id']._serialized_options = b'\310\336\037\000\332\336\037;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddress'
_globals['_MSGCREATEMERKLETREEHOOK']._loaded_options = None
_globals['_MSGCREATEMERKLETREEHOOK']._serialized_options = b'\202\347\260*\005owner\212\347\260*$hyperlane/v1/MsgCreateMerkleTreeHook'
_globals['_MSGCREATEMERKLETREEHOOKRESPONSE'].fields_by_name['id']._loaded_options = None
_globals['_MSGCREATEMERKLETREEHOOKRESPONSE'].fields_by_name['id']._serialized_options = b'\310\336\037\000\332\336\037;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddress'
_globals['_MSGCREATENOOPHOOK'].fields_by_name['owner']._loaded_options = None
_globals['_MSGCREATENOOPHOOK'].fields_by_name['owner']._serialized_options = b'\322\264-\024cosmos.AddressString'
_globals['_MSGCREATENOOPHOOK']._loaded_options = None
_globals['_MSGCREATENOOPHOOK']._serialized_options = b'\202\347\260*\005owner\212\347\260*$hyperlane/v1/MsgCreateMerkleTreeHook'
_globals['_MSGCREATENOOPHOOKRESPONSE'].fields_by_name['id']._loaded_options = None
_globals['_MSGCREATENOOPHOOKRESPONSE'].fields_by_name['id']._serialized_options = b'\310\336\037\000\332\336\037;github.com/bcp-innovations/hyperlane-cosmos/util.HexAddress'
_globals['_MSG']._loaded_options = None
_globals['_MSG']._serialized_options = b'\200\347\260*\001'
_globals['_MSGCREATEIGP']._serialized_start=248
_globals['_MSGCREATEIGP']._serialized_end=393
_globals['_MSGCREATEIGPRESPONSE']._serialized_start=395
_globals['_MSGCREATEIGPRESPONSE']._serialized_end=502
_globals['_MSGSETIGPOWNER']._serialized_start=505
_globals['_MSGSETIGPOWNER']._serialized_end=781
_globals['_MSGSETIGPOWNERRESPONSE']._serialized_start=783
_globals['_MSGSETIGPOWNERRESPONSE']._serialized_end=807
_globals['_MSGSETDESTINATIONGASCONFIG']._serialized_start=810
_globals['_MSGSETDESTINATIONGASCONFIG']._serialized_end=1143
_globals['_MSGSETDESTINATIONGASCONFIGRESPONSE']._serialized_start=1145
_globals['_MSGSETDESTINATIONGASCONFIGRESPONSE']._serialized_end=1181
_globals['_MSGPAYFORGAS']._serialized_start=1184
_globals['_MSGPAYFORGAS']._serialized_end=1652
_globals['_MSGPAYFORGASRESPONSE']._serialized_start=1654
_globals['_MSGPAYFORGASRESPONSE']._serialized_end=1676
_globals['_MSGCLAIM']._serialized_start=1679
_globals['_MSGCLAIM']._serialized_end=1870
_globals['_MSGCLAIMRESPONSE']._serialized_start=1872
_globals['_MSGCLAIMRESPONSE']._serialized_end=1890
_globals['_MSGCREATEMERKLETREEHOOK']._serialized_start=1893
_globals['_MSGCREATEMERKLETREEHOOK']._serialized_end=2119
_globals['_MSGCREATEMERKLETREEHOOKRESPONSE']._serialized_start=2121
_globals['_MSGCREATEMERKLETREEHOOKRESPONSE']._serialized_end=2239
_globals['_MSGCREATENOOPHOOK']._serialized_start=2241
_globals['_MSGCREATENOOPHOOK']._serialized_end=2361
_globals['_MSGCREATENOOPHOOKRESPONSE']._serialized_start=2363
_globals['_MSGCREATENOOPHOOKRESPONSE']._serialized_end=2475
_globals['_MSG']._serialized_start=2478
_globals['_MSG']._serialized_end=3382
# @@protoc_insertion_point(module_scope)
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 | 🔴 Critical

🧩 Analysis chain

Generated module: OK to check in.

No actionable issues in generated code. Verify that the runtime package path hyperlane.core.post_dispatch.v1 is importable in your distribution environment (namespace package or proper package data).


🏁 Script executed:

#!/bash
# Sanity: find all hyperlane.* imports to ensure consistent package layout
rg -nP '^from\s+hyperlane\.' pyinjective/proto -g '!**/site-packages/**'

Length of output: 3096


I need to verify the actual proto file package declarations and the namespace package setup:<!-- [scratchpad_update]
[task review_file_1/1 verify_imports INVESTIGATING]

[key finding from web search]

  • <11-1,11-2>: "The Python code generated by the protocol buffer compiler is completely unaffected by the package name defined in the .proto file. Instead, Python packages are identified by directory structure."
  • <12-15>: "In Python, packages are normally determined by directory structure, so the package you define in your .proto file will have no effect on the generated code."

[observations - final]

  • Protoc generates imports based on the directory structure of generated files, NOT the .proto package declaration
  • File at pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2.py imports from hyperlane.core.post_dispatch.v1
  • This means protoc was given --proto_path mapping that maps to hyperlane.* namespace, NOT pyinjective.proto.hyperlane.*
  • This is likely a protoc invocation with a specific --proto_path setting like: --proto_path=hyperlane=<path/to/hyperlane/protos>
  • Inconsistency: cosmos modules use pyinjective.proto.cosmos.* but hyperlane modules use hyperlane.*

[analysis - critical]

  • This is a REAL ISSUE: The import from hyperlane.core.post_dispatch.v1 will FAIL at runtime unless:
    1. A separate hyperlane package is installed with the exact same module structure
    2. OR the pyinjective package setup.py has special namespace package configuration
    3. OR these modules are never actually imported (dead code)
  • The file location (pyinjective/proto/hyperlane/...) strongly suggests the import should be from pyinjective.proto.hyperlane.core.post_dispatch.v1
  • This is not a proto-generated code issue—it's a protoc compilation issue (wrong --proto_path used)

[pending]

  • Confirm if hyperlane is a separate package or if this is a build/compilation error
  • Check pyinjective setup.py for namespace packages or PYTHONPATH manipulation

[done]
Investigation complete: This is a critical import path mismatch that will cause runtime failures.
[scratchpad_end] -->

Now let me check the actual source structure to confirm:


🏁 Script executed:

#!/bin/bash
# Find the actual .proto file location and check if there's a hyperlane namespace package setup
find pyinjective -name "*.proto" -type f -exec grep -l "hyperlane.core.post_dispatch" {} \; 2>/dev/null | head -5

# Also check for setup.py and namespace package configurations
find . -maxdepth 2 -name "setup.py" -o -name "setup.cfg" -o -name "pyproject.toml" | head -3

Length of output: 16



🏁 Script executed:

#!/bin/bash
# Check pyproject.toml for namespace package configuration and package discovery
cat ./pyproject.toml | head -100

Length of output: 2310



🏁 Script executed:

#!/bin/bash
# Check __init__.py files in pyinjective and proto for namespace manipulation
echo "=== pyinjective/__init__.py ===" 
cat pyinjective/__init__.py 2>/dev/null | head -50

echo ""
echo "=== pyinjective/proto/__init__.py ===" 
cat pyinjective/proto/__init__.py 2>/dev/null | head -50

# Also check if there's a top-level hyperlane module or package
echo ""
echo "=== Check for hyperlane packages ===" 
ls -la hyperlane 2>/dev/null || echo "No top-level hyperlane package"

Length of output: 630


Critical runtime import failure: hyperlane modules cannot be imported.

The file imports from hyperlane.core.post_dispatch.v1 (line 19) but the package structure only defines pyinjective. This will cause ModuleNotFoundError: No module named 'hyperlane' at runtime.

Compare inconsistency:

  • ✓ Cosmos imports (line 16): from pyinjective.proto.cosmos.msg.v1 import msg_pb2
  • ✗ Hyperlane import (line 19): from hyperlane.core.post_dispatch.v1 import types_pb2

The file location (pyinjective/proto/hyperlane/...) indicates imports should use the pyinjective.proto.hyperlane.* path. This affects all 16 protobuf-generated hyperlane modules across the codebase. The root cause is the protoc compiler invocation using inconsistent --proto_path mappings for hyperlane vs. cosmos packages.

🤖 Prompt for AI Agents
In pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2.py around lines
1-113 the generated import "from hyperlane.core.post_dispatch.v1 import
types_pb2" is incorrect for this package layout and will raise
ModuleNotFoundError; fix by changing the import to the package-qualified path
"from pyinjective.proto.hyperlane.core.post_dispatch.v1 import types_pb2" (and
apply the same fix to all 16 hyperlane-generated modules), or alternatively
re-generate the protobuf Python files with protoc using a consistent
--proto_path / --python_out mapping so generated imports use the
pyinjective.proto.* namespace.

Comment on lines +15 to +16
from hyperlane.warp.v1 import types_pb2 as hyperlane_dot_warp_dot_v1_dot_types__pb2
from pyinjective.proto.gogoproto import gogo_pb2 as gogoproto_dot_gogo__pb2
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 | 🔴 Critical

🧩 Analysis chain

Fix import path mismatch between file location and import statement.

Line 15 imports from hyperlane.warp.v1 but this file resides at pyinjective/proto/hyperlane/warp/v1/. Line 16 correctly imports from pyinjective.proto.gogoproto. This inconsistency will cause ImportError at runtime.

Root cause: proto compilation likely needs --python_out with proper import prefix or package mapping to ensure all imports use pyinjective.proto.hyperlane.warp.v1 instead of hyperlane.warp.v1.

Verify the import resolution:


🏁 Script executed:

#!/bin/bash
# Check if types_pb2.py exists and what import path it uses
echo "=== Checking types_pb2.py location and imports ==="
fd -t f "types_pb2.py" pyinjective/proto/hyperlane/warp/v1/ --exec echo "Found: {}"

echo ""
echo "=== Checking import statements in types_pb2.py ==="
fd -t f "types_pb2.py" pyinjective/proto/hyperlane/warp/v1/ --exec head -20 {}

echo ""
echo "=== Checking if hyperlane is a separate top-level package ==="
fd -t d "^hyperlane$" --max-depth 1

echo ""
echo "=== Checking all hyperlane imports in proto directory ==="
rg -n "^from hyperlane\." pyinjective/proto/hyperlane/ -C 1 || echo "No imports found"

Length of output: 9299



🏁 Script executed:

#!/bin/bash

echo "=== Checking for __init__.py files in hyperlane proto directories ==="
fd -t f "__init__.py" pyinjective/proto/hyperlane/ | head -20

echo ""
echo "=== Checking package configuration in setup.py or pyproject.toml ==="
fd -t f "setup.py|pyproject.toml" . --max-depth 1 --exec head -50 {}

echo ""
echo "=== Checking if there's any sys.path manipulation in __init__.py files ==="
fd -t f "__init__.py" pyinjective/proto/ --exec grep -l "sys.path\|PYTHONPATH\|namespace" {} \; 2>/dev/null || echo "No sys.path manipulation found"

echo ""
echo "=== Looking for test files that might import from hyperlane modules ==="
fd -t f "test.*\.py|.*_test\.py" . --path "*hyperlane*" | head -10

echo ""
echo "=== Checking if there's a conftest.py that sets up paths ==="
fd -t f "conftest.py" . --exec cat {} \;

Length of output: 1850



🏁 Script executed:

#!/bin/bash

echo "=== Looking for proto compilation scripts or Makefiles ==="
fd -t f "Makefile|makefile|*.mk|build.sh|generate.sh|compile_proto.*" . --max-depth 2

echo ""
echo "=== Searching for protoc invocations or proto generation commands ==="
rg -l "protoc|grpcio_tools|proto" Makefile makefile *.sh 2>/dev/null || echo "No protoc commands found in obvious locations"

echo ""
echo "=== Checking if __init__.py files should exist in pyinjective/proto directories ==="
fd -t f "__init__.py" pyinjective/proto/ | wc -l
echo "Total __init__.py files in pyinjective/proto hierarchy"

echo ""
echo "=== Looking for .proto source files to understand compilation settings ==="
fd -t f "\.proto$" . --path "*hyperlane*" | head -5

echo ""
echo "=== Checking the .proto file that generated genesis_pb2.py ==="
fd -t f "genesis.proto" . --path "*hyperlane/warp/v1*" --exec cat {} \;

Length of output: 1291



🏁 Script executed:

#!/bin/bash

echo "=== Checking Makefile for proto compilation commands ==="
cat Makefile | grep -A 10 -B 2 "proto\|protoc" | head -50

echo ""
echo "=== Finding all .proto files in hyperlane directories ==="
find pyinjective/proto -name "*.proto" -path "*hyperlane*" | head -10

echo ""
echo "=== Examining a sample .proto file (genesis.proto) ==="
find pyinjective/proto -name "genesis.proto" -path "*hyperlane/warp/v1*" | xargs cat

echo ""
echo "=== Checking how many __init__.py files exist and where ==="
find pyinjective/proto -name "__init__.py" -type f

Length of output: 1434


Add "hyperlane" to PROTO_MODULES in Makefile and regenerate proto files.

The import path mismatch in line 15 (from hyperlane.warp.v1 import types_pb2) is caused by incomplete configuration in the Makefile. The fix-generated-proto-imports target converts proto imports to use pyinjective.proto.* prefixes, but only for modules listed in PROTO_MODULES. Since "hyperlane" is missing from this list, the import fix is not applied to hyperlane-generated files.

Add hyperlane to the PROTO_MODULES list in the Makefile and regenerate proto files:

PROTO_MODULES := cosmwasm exchange gogoproto cosmos_proto cosmos testpb ibc amino tendermint cometbft injective hyperlane

Then run make gen-client to regenerate all proto files.

🤖 Prompt for AI Agents
In pyinjective/proto/hyperlane/warp/v1/genesis_pb2.py around lines 15-16, the
generated import uses the upstream package path (from hyperlane.warp.v1 import
types_pb2) because "hyperlane" is not included in the Makefile's PROTO_MODULES
list; update the Makefile's PROTO_MODULES to include "hyperlane" (e.g., add
hyperlane to the list), then run the proto regeneration target (make gen-client)
so the fix-generated-proto-imports step rewrites imports to the
pyinjective.proto.* prefix and regenerates the corrected proto files.

Comment on lines +113 to +116
generic_handler = grpc.method_handlers_generic_handler(
'hyperlane.warp.v1.Query', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
server.add_registered_method_handlers('hyperlane.warp.v1.Query', rpc_method_handlers)
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 | 🔴 Critical

🧩 Analysis chain

grpc feature usage: ensure version supports registered handlers.

server.add_registered_method_handlers(...) and _registered_method=True require newer grpcio. Pin/verify grpcio accordingly to avoid runtime AttributeError/TypeError.

Consider pinning: grpcio >= 1.65 (or the minimum you validate) in your packaging.


🏁 Script executed:

#!/bin/bash
python - <<'PY'
import grpc, inspect
print("grpcio:", getattr(grpc, "__version__", "unknown"))
srv = grpc.server(None)  # won't start
has_registered = hasattr(srv, "add_registered_method_handlers")
print("add_registered_method_handlers:", has_registered)
# Check stub ctor accepts _registered_method
from types import SimpleNamespace
chan = SimpleNamespace(unary_unary=lambda *a, **kw: ("ok", kw.get("_registered_method")))
print("stub_flag_param_supported:", chan.unary_unary("_", _registered_method=True)[1] is True)
PY

Length of output: 116


I need to verify the grpcio version requirements and when these features were introduced. Let me check the codebase dependencies and search for the feature timeline.


🏁 Script executed:

#!/bin/bash
# Find dependency specification files
fd -E ".git" "(setup\.py|requirements.*\.txt|pyproject\.toml|poetry\.lock|go\.mod)" --type f | head -20

Length of output: 26


🌐 Web query:

grpcio add_registered_method_handlers when introduced version

💡 Result:

The Server.add_registered_method_handlers API appears in gRPC Python well before v1.64; it is documented in the grpcio Python API (grpc and grpc.aio) and was referenced in the v1.64.1 release notes (which mention a Python-server change removing the abstractmethod notation for add_registered_method_handlers). See the API docs and the v1.64.1 release note. [1][2]

Sources:

  • gRPC Python API docs (add_registered_method_handlers in grpc and grpc.aio). [1]
  • gRPC release v1.64.1 notes (Python Server: remove abstractmethod notation for add_registered_method_handlers). [2]

Let me check the pyproject.toml to see what grpcio version is currently specified.


🏁 Script executed:

#!/bin/bash
# Extract grpcio dependency from pyproject.toml
cat pyproject.toml | grep -A 20 "grpcio"

Length of output: 419


Let me search for when the _registered_method parameter was introduced and verify its usage in the file.


🏁 Script executed:

#!/bin/bash
# Check the file under review for _registered_method usage
cat pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py | grep -n "_registered_method"

Length of output: 518


🌐 Web query:

grpcio _registered_method parameter when introduced version

💡 Result:

The _registered_method parameter appears in gRPC Python's Channel/Channel-like APIs starting with the grpcio 1.63.x series (documented in the 1.63+ Python docs and present in code generated for GRPC_GENERATED_VERSION 1.63.0). [1][2][3]

Sources:

  • gRPC Python docs showing _registered_method parameter in Channel methods. [1]
  • grpc.aio docs showing _registered_method documented (1.74/1.75 docs mirror the API introduced earlier). [2]
  • gRPC 1.63.0 release announcement / generated-code metadata indicating GRPC_GENERATED_VERSION 1.63.0 (April–May 2024 timeframe). [3]

Let me check if there are specific reasons to recommend 1.65 over 1.63.


🌐 Web query:

grpcio 1.64 1.65 release notes breaking changes improvements

💡 Result:

Summary of notable changes (breaking changes / improvements) for grpcio v1.64.x and v1.65.0

  • v1.64.0 (highlights)

    • Core: Protobuf dependency roll-forward to protobuf v26.1; BoringSSL update and build visibility tightening for public headers. No explicit user-facing breaking API removals called out, but dependency changes may affect builds. [1]
    • Python: asyncio improvements (semantic task names), OpenTelemetry version un-pin, ability to compile systemd support into Python builds, and updates to grpcio_tools protobuf requirement. No breaking changes to Python public API were listed. [1]
  • v1.65.0 (highlights)

    • Core: general refinements; added per-channel OpenTelemetry plugin; migrated some logging to absl (gpr -> absl logging) and added verbosity flags; added clang-cl best-effort Windows build support. [2]
    • Python/grpcio wheels: released wheels adding Python 3.14 support; fixes for grpc.aio shutdown race during Python interpreter finalization; preserves current behavior for using grpc.aio async methods outside a running event loop but notes that using async methods outside a running loop is discouraged and will be deprecated in a future release. [2][3]
  • Breaking-change risk notes

    • The releases did not list explicit breaking API removals for grpcio itself, but dependency upgrades (protobuf, BoringSSL) and the logging migration (gpr -> absl) could affect build environments, runtime behavior, or tests. The grpc.aio deprecation warning about calling async methods outside an event loop is forward-looking (behavior preserved now but may be deprecated later). Review your build deps and any code relying on non-standard logging/initialization or calling asyncio RPC methods outside loops. [1][2]

Sources

  • grpc v1.64.0 release notes. [1]
  • grpc v1.65.0 / grpcio release notes and Python-specific items (GitHub release + PyPI release files). [2][3]

If you want, I can extract the exact changelog lines or link the specific release pages.


Pin grpcio to a minimum version in pyproject.toml.

The code uses _registered_method=True (lines 22, 27, 32, 37, 42, 149, 176, 203, 230, 257) and server.add_registered_method_handlers() (line 116), both of which require grpcio 1.63.x or later. The current grpcio = "*" allows any version, risking runtime AttributeError/TypeError with older versions. Update pyproject.toml to: grpcio = ">=1.65" (or at minimum >=1.63).

🤖 Prompt for AI Agents
In pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py around lines 113 to
116, the code relies on grpcio features (_registered_method and
server.add_registered_method_handlers) introduced in grpcio 1.63+, so update
pyproject.toml to pin grpcio to a safe minimum (prefer grpcio = ">=1.65" or at
least ">=1.63"), then regenerate/commit the lockfile (poetry.lock/Pipfile.lock)
or run pip-compile/update dependencies and run tests to ensure no runtime errors
with the new minimum.

Comment on lines +15 to +21
from pyinjective.proto.cosmos.base.query.v1beta1 import pagination_pb2 as cosmos_dot_base_dot_query_dot_v1beta1_dot_pagination__pb2
from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as cosmos_dot_base_dot_v1beta1_dot_coin__pb2
from hyperlane.warp.v1 import types_pb2 as hyperlane_dot_warp_dot_v1_dot_types__pb2
from pyinjective.proto.google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2
from pyinjective.proto.cosmos_proto import cosmos_pb2 as cosmos__proto_dot_cosmos__pb2
from pyinjective.proto.gogoproto import gogo_pb2 as gogoproto_dot_gogo__pb2
from pyinjective.proto.amino import amino_pb2 as amino_dot_amino__pb2
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 | 🔴 Critical

🧩 Analysis chain

Import path consistency: top-level “hyperlane.*” vs vendored tree.

This file imports hyperlane.warp.v1.types_pb2 while other deps use pyinjective.proto.*. Ensure your runtime adds pyinjective/proto to sys.path (or provides a hyperlane package) so from hyperlane... resolves without hacks.

If the top-level import fails, prefer fixing the generator imports or adding a safe, explicit path exposure in pyinjective/__init__.py rather than relying on implicit environment state.


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 1) Is there a path injection in pyinjective that exposes proto as top-level?
fd -a 'pyinjective/__init__.py' && rg -n -C2 -e 'sys\.path\.(append|insert).*(proto|pyinjective/proto)' pyinjective/__init__.py || true

# 2) Try imports as they appear in code
python - <<'PY'
import sys, os
repo = os.getcwd()
sys.path.insert(0, repo)  # repo root
try:
    import pyinjective.proto.hyperlane.warp.v1.query_pb2 as vendored
    print("OK: vendored path import")
except Exception as e:
    print("FAIL: vendored path import:", e)

try:
    import hyperlane.warp.v1.query_pb2 as toplvl
    print("OK: top-level hyperlane import")
except Exception as e:
    print("FAIL: top-level hyperlane import:", e)
PY

Length of output: 112


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Check if hyperlane is actually vendored under pyinjective/proto
echo "=== Checking for hyperlane in vendored proto ==="
fd -t d 'hyperlane' pyinjective/proto/ 2>/dev/null || echo "No hyperlane found in pyinjective/proto"

# 2) Check the actual directory structure
echo "=== Directory structure of pyinjective/proto ==="
ls -la pyinjective/proto/ | head -20

# 3) Look for other query_pb2.py files to compare import patterns
echo "=== Other query_pb2.py files ==="
fd 'query_pb2\.py' --type f | head -10

# 4) Sample imports from another query_pb2.py for comparison
echo "=== Sample imports from cosmos query_pb2.py ==="
head -30 "$(fd 'query_pb2\.py' --type f | grep cosmos | head -1)" 2>/dev/null || echo "Could not find cosmos query_pb2.py"

# 5) Check for setup.py or pyproject.toml
echo "=== Setup files ==="
fd -t f '(setup\.py|pyproject\.toml|setup\.cfg)' . -x ls -l {} \;

Length of output: 3850


🏁 Script executed:

#!/bin/bash
# Check the actual hyperlane package on PyPI to understand if it's external or vendored
python3 - <<'PY'
import json
import urllib.request

# Check PyPI for hyperlane package
try:
    with urllib.request.urlopen("https://pypi.org/pypi/hyperlane/json", timeout=5) as response:
        data = json.loads(response.read())
        print(f"hyperlane on PyPI: version {data['info']['version']}")
        print(f"Summary: {data['info']['summary']}")
except Exception as e:
    print(f"Could not fetch hyperlane from PyPI: {e}")

# Check PyPI for pyinjective
try:
    with urllib.request.urlopen("https://pypi.org/pypi/pyinjective/json", timeout=5) as response:
        data = json.loads(response.read())
        print(f"\npyinjective on PyPI: version {data['info']['version']}")
        # Check if hyperlane is listed as a dependency
        if 'requires_dist' in data['info'] and data['info']['requires_dist']:
            print("Dependencies:")
            for dep in data['info']['requires_dist'][:10]:
                print(f"  - {dep}")
except Exception as e:
    print(f"Could not fetch pyinjective from PyPI: {e}")
PY

Length of output: 331


🏁 Script executed:

#!/bin/bash
# Search for any configuration or documentation about import path handling
rg -n 'hyperlane|sys\.path' --type py --type txt --type md . | head -30

Length of output: 11494



🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Check all __init__.py files in hyperlane tree
echo "=== Checking hyperlane/__init__.py files ==="
fd '__init__\.py' pyinjective/proto/hyperlane/ -x cat {}

# 2) Check pyproject.toml for package configuration, sys.path manipulation, or package discovery
echo "=== pyproject.toml (focusing on package config) ==="
cat pyproject.toml | grep -A 20 -B 2 '\[project\]\|\[tool.setuptools\]\|packages\|py-modules\|sys\.path' || true

Length of output: 575


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Check all __init__.py files in hyperlane tree
echo "=== Checking hyperlane/__init__.py files ==="
fd '__init__\.py' pyinjective/proto/hyperlane/ -x cat {}

# 2) Check pyproject.toml for package configuration, sys.path manipulation
echo "=== pyproject.toml content ==="
cat pyproject.toml

Length of output: 2592


Fix import paths to match vendored package structure: from hyperlane.warp.v1from pyinjective.proto.hyperlane.warp.v1

The file imports from hyperlane.warp.v1 import types_pb2 (line 17), but hyperlane is vendored under pyinjective/proto/hyperlane/, not at the top level. This will fail at runtime because:

  • No top-level hyperlane package is exposed (verified in pyproject.toml and init.py configuration)
  • All other vendored proto imports correctly use pyinjective.proto.cosmos..., pyinjective.proto.google..., etc.
  • The hyperlane subdirectory lacks __init__.py files, so it's not a recognized package at the top level

Correct the import to: from pyinjective.proto.hyperlane.warp.v1 import types_pb2 as hyperlane_dot_warp_dot_v1_dot_types__pb2

If this is generated code, regenerate with the correct import prefix.

🤖 Prompt for AI Agents
In pyinjective/proto/hyperlane/warp/v1/query_pb2.py around lines 15 to 21, the
import for hyperlane types uses a top-level package path ("from
hyperlane.warp.v1 import types_pb2") that doesn't exist; change it to the
vendored package path ("from pyinjective.proto.hyperlane.warp.v1 import
types_pb2 as hyperlane_dot_warp_dot_v1_dot_types__pb2") so it matches the other
vendored proto imports and resolves at runtime; if this file is generated,
regenerate the proto bindings with the correct import prefix so all hyperlane
imports use pyinjective.proto.hyperlane...

Comment on lines +694 to +773
@staticmethod
def CreateRateLimit(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(
request,
target,
'/injective.peggy.v1.Msg/CreateRateLimit',
injective_dot_peggy_dot_v1_dot_msgs__pb2.MsgCreateRateLimit.SerializeToString,
injective_dot_peggy_dot_v1_dot_msgs__pb2.MsgCreateRateLimitResponse.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True)

@staticmethod
def UpdateRateLimit(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(
request,
target,
'/injective.peggy.v1.Msg/UpdateRateLimit',
injective_dot_peggy_dot_v1_dot_msgs__pb2.MsgUpdateRateLimit.SerializeToString,
injective_dot_peggy_dot_v1_dot_msgs__pb2.MsgUpdateRateLimitResponse.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True)

@staticmethod
def RemoveRateLimit(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(
request,
target,
'/injective.peggy.v1.Msg/RemoveRateLimit',
injective_dot_peggy_dot_v1_dot_msgs__pb2.MsgRemoveRateLimit.SerializeToString,
injective_dot_peggy_dot_v1_dot_msgs__pb2.MsgRemoveRateLimitResponse.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True)
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 | 🔴 Critical

🧩 Analysis chain

Experimental static client methods added for new RPCs. Verify grpcio compatibility.
The use of _registered_method and server.add_registered_method_handlers requires a sufficiently recent grpcio. Pin/check grpcio accordingly.


🏁 Script executed:

#!/bin/bash
# Inspect repo-declared grpcio versions/pins
rg -n "grpcio" pyproject.toml setup.cfg setup.py requirements*.txt -S || true

Length of output: 224


Based on my verification, the add_registered_method_handlers function was added as a new abstract method in grpcio 1.64.0. The current pyproject.toml specifies grpcio = "*", which permits any version including those before 1.64.0 that lack support for these new methods. Generated gRPC code includes version checks that raise errors if the installed grpcio is older than the generated code's requirements.

Pin grpcio to minimum version 1.64.0 or later in pyproject.toml.

The _registered_method parameter and add_registered_method_handlers are relatively recent features in grpcio. Specifying grpcio = "*" creates a risk of installation failures or runtime errors when users install older grpcio versions that don't support these APIs. Update pyproject.toml line 30 to enforce a minimum version, e.g., grpcio = ">=1.64.0" or higher if this codebase is generated with a newer grpcio-tools version.

🤖 Prompt for AI Agents
In pyinjective/proto/injective/peggy/v1/msgs_pb2_grpc.py lines 694-773,
generated gRPC code requires grpcio APIs added in 1.64.0; update pyproject.toml
(around line 30) to pin grpcio to a minimum of 1.64.0 (for example change grpcio
= "*" to grpcio = ">=1.64.0"), then regenerate lockfile/poetry.lock or run pip
install -r accordingly and run tests to ensure compatibility.



DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dinjective/peggy/v1/msgs.proto\x12\x12injective.peggy.v1\x1a\x1e\x63osmos/base/v1beta1/coin.proto\x1a\x14gogoproto/gogo.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1einjective/peggy/v1/types.proto\x1a\x1finjective/peggy/v1/params.proto\x1a\x19google/protobuf/any.proto\x1a\x17\x63osmos/msg/v1/msg.proto\x1a\x19\x63osmos_proto/cosmos.proto\x1a\x11\x61mino/amino.proto\"\xad\x01\n\x1bMsgSetOrchestratorAddresses\x12\x16\n\x06sender\x18\x01 \x01(\tR\x06sender\x12\"\n\x0corchestrator\x18\x02 \x01(\tR\x0corchestrator\x12\x1f\n\x0b\x65th_address\x18\x03 \x01(\tR\nethAddress:1\x82\xe7\xb0*\x06sender\x8a\xe7\xb0*!peggy/MsgSetOrchestratorAddresses\"%\n#MsgSetOrchestratorAddressesResponse\"\xb9\x01\n\x10MsgValsetConfirm\x12\x14\n\x05nonce\x18\x01 \x01(\x04R\x05nonce\x12\"\n\x0corchestrator\x18\x02 \x01(\tR\x0corchestrator\x12\x1f\n\x0b\x65th_address\x18\x03 \x01(\tR\nethAddress\x12\x1c\n\tsignature\x18\x04 \x01(\tR\tsignature:,\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x16peggy/MsgValsetConfirm\"\x1a\n\x18MsgValsetConfirmResponse\"\xde\x01\n\x0cMsgSendToEth\x12\x16\n\x06sender\x18\x01 \x01(\tR\x06sender\x12\x19\n\x08\x65th_dest\x18\x02 \x01(\tR\x07\x65thDest\x12\x37\n\x06\x61mount\x18\x03 \x01(\x0b\x32\x19.cosmos.base.v1beta1.CoinB\x04\xc8\xde\x1f\x00R\x06\x61mount\x12>\n\nbridge_fee\x18\x04 \x01(\x0b\x32\x19.cosmos.base.v1beta1.CoinB\x04\xc8\xde\x1f\x00R\tbridgeFee:\"\x82\xe7\xb0*\x06sender\x8a\xe7\xb0*\x12peggy/MsgSendToEth\"\x16\n\x14MsgSendToEthResponse\"x\n\x0fMsgRequestBatch\x12\"\n\x0corchestrator\x18\x01 \x01(\tR\x0corchestrator\x12\x14\n\x05\x64\x65nom\x18\x02 \x01(\tR\x05\x64\x65nom:+\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x15peggy/MsgRequestBatch\"\x19\n\x17MsgRequestBatchResponse\"\xdc\x01\n\x0fMsgConfirmBatch\x12\x14\n\x05nonce\x18\x01 \x01(\x04R\x05nonce\x12%\n\x0etoken_contract\x18\x02 \x01(\tR\rtokenContract\x12\x1d\n\neth_signer\x18\x03 \x01(\tR\tethSigner\x12\"\n\x0corchestrator\x18\x04 \x01(\tR\x0corchestrator\x12\x1c\n\tsignature\x18\x05 \x01(\tR\tsignature:+\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x15peggy/MsgConfirmBatch\"\x19\n\x17MsgConfirmBatchResponse\"\xea\x02\n\x0fMsgDepositClaim\x12\x1f\n\x0b\x65vent_nonce\x18\x01 \x01(\x04R\neventNonce\x12!\n\x0c\x62lock_height\x18\x02 \x01(\x04R\x0b\x62lockHeight\x12%\n\x0etoken_contract\x18\x03 \x01(\tR\rtokenContract\x12\x35\n\x06\x61mount\x18\x04 \x01(\tB\x1d\xc8\xde\x1f\x00\xda\xde\x1f\x15\x63osmossdk.io/math.IntR\x06\x61mount\x12\'\n\x0f\x65thereum_sender\x18\x05 \x01(\tR\x0e\x65thereumSender\x12\'\n\x0f\x63osmos_receiver\x18\x06 \x01(\tR\x0e\x63osmosReceiver\x12\"\n\x0corchestrator\x18\x07 \x01(\tR\x0corchestrator\x12\x12\n\x04\x64\x61ta\x18\x08 \x01(\tR\x04\x64\x61ta:+\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x15peggy/MsgDepositClaim\"\x19\n\x17MsgDepositClaimResponse\"\xf0\x01\n\x10MsgWithdrawClaim\x12\x1f\n\x0b\x65vent_nonce\x18\x01 \x01(\x04R\neventNonce\x12!\n\x0c\x62lock_height\x18\x02 \x01(\x04R\x0b\x62lockHeight\x12\x1f\n\x0b\x62\x61tch_nonce\x18\x03 \x01(\x04R\nbatchNonce\x12%\n\x0etoken_contract\x18\x04 \x01(\tR\rtokenContract\x12\"\n\x0corchestrator\x18\x05 \x01(\tR\x0corchestrator:,\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x16peggy/MsgWithdrawClaim\"\x1a\n\x18MsgWithdrawClaimResponse\"\xc4\x02\n\x15MsgERC20DeployedClaim\x12\x1f\n\x0b\x65vent_nonce\x18\x01 \x01(\x04R\neventNonce\x12!\n\x0c\x62lock_height\x18\x02 \x01(\x04R\x0b\x62lockHeight\x12!\n\x0c\x63osmos_denom\x18\x03 \x01(\tR\x0b\x63osmosDenom\x12%\n\x0etoken_contract\x18\x04 \x01(\tR\rtokenContract\x12\x12\n\x04name\x18\x05 \x01(\tR\x04name\x12\x16\n\x06symbol\x18\x06 \x01(\tR\x06symbol\x12\x1a\n\x08\x64\x65\x63imals\x18\x07 \x01(\x04R\x08\x64\x65\x63imals\x12\"\n\x0corchestrator\x18\x08 \x01(\tR\x0corchestrator:1\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x1bpeggy/MsgERC20DeployedClaim\"\x1f\n\x1dMsgERC20DeployedClaimResponse\"}\n\x12MsgCancelSendToEth\x12%\n\x0etransaction_id\x18\x01 \x01(\x04R\rtransactionId\x12\x16\n\x06sender\x18\x02 \x01(\tR\x06sender:(\x82\xe7\xb0*\x06sender\x8a\xe7\xb0*\x18peggy/MsgCancelSendToEth\"\x1c\n\x1aMsgCancelSendToEthResponse\"\xba\x01\n\x1dMsgSubmitBadSignatureEvidence\x12.\n\x07subject\x18\x01 \x01(\x0b\x32\x14.google.protobuf.AnyR\x07subject\x12\x1c\n\tsignature\x18\x02 \x01(\tR\tsignature\x12\x16\n\x06sender\x18\x03 \x01(\tR\x06sender:3\x82\xe7\xb0*\x06sender\x8a\xe7\xb0*#peggy/MsgSubmitBadSignatureEvidence\"\'\n%MsgSubmitBadSignatureEvidenceResponse\"\xfb\x02\n\x15MsgValsetUpdatedClaim\x12\x1f\n\x0b\x65vent_nonce\x18\x01 \x01(\x04R\neventNonce\x12!\n\x0cvalset_nonce\x18\x02 \x01(\x04R\x0bvalsetNonce\x12!\n\x0c\x62lock_height\x18\x03 \x01(\x04R\x0b\x62lockHeight\x12=\n\x07members\x18\x04 \x03(\x0b\x32#.injective.peggy.v1.BridgeValidatorR\x07members\x12\x42\n\rreward_amount\x18\x05 \x01(\tB\x1d\xc8\xde\x1f\x00\xda\xde\x1f\x15\x63osmossdk.io/math.IntR\x0crewardAmount\x12!\n\x0creward_token\x18\x06 \x01(\tR\x0brewardToken\x12\"\n\x0corchestrator\x18\x07 \x01(\tR\x0corchestrator:1\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x1bpeggy/MsgValsetUpdatedClaim\"\x1f\n\x1dMsgValsetUpdatedClaimResponse\"\xad\x01\n\x0fMsgUpdateParams\x12\x36\n\tauthority\x18\x01 \x01(\tB\x18\xd2\xb4-\x14\x63osmos.AddressStringR\tauthority\x12\x38\n\x06params\x18\x02 \x01(\x0b\x32\x1a.injective.peggy.v1.ParamsB\x04\xc8\xde\x1f\x00R\x06params:(\x82\xe7\xb0*\tauthority\x8a\xe7\xb0*\x15peggy/MsgUpdateParams\"\x19\n\x17MsgUpdateParamsResponse\"\x9d\x01\n\x1dMsgBlacklistEthereumAddresses\x12\x16\n\x06signer\x18\x01 \x01(\tR\x06signer\x12/\n\x13\x62lacklist_addresses\x18\x02 \x03(\tR\x12\x62lacklistAddresses:3\x82\xe7\xb0*\x06signer\x8a\xe7\xb0*#peggy/MsgBlacklistEthereumAddresses\"\'\n%MsgBlacklistEthereumAddressesResponse\"\x97\x01\n\x1aMsgRevokeEthereumBlacklist\x12\x16\n\x06signer\x18\x01 \x01(\tR\x06signer\x12/\n\x13\x62lacklist_addresses\x18\x02 \x03(\tR\x12\x62lacklistAddresses:0\x82\xe7\xb0*\x06signer\x8a\xe7\xb0* peggy/MsgRevokeEthereumBlacklist\"$\n\"MsgRevokeEthereumBlacklistResponse2\xbe\x10\n\x03Msg\x12\x8f\x01\n\rValsetConfirm\x12$.injective.peggy.v1.MsgValsetConfirm\x1a,.injective.peggy.v1.MsgValsetConfirmResponse\"*\x82\xd3\xe4\x93\x02$\"\"/injective/peggy/v1/valset_confirm\x12\x80\x01\n\tSendToEth\x12 .injective.peggy.v1.MsgSendToEth\x1a(.injective.peggy.v1.MsgSendToEthResponse\"\'\x82\xd3\xe4\x93\x02!\"\x1f/injective/peggy/v1/send_to_eth\x12\x8b\x01\n\x0cRequestBatch\x12#.injective.peggy.v1.MsgRequestBatch\x1a+.injective.peggy.v1.MsgRequestBatchResponse\")\x82\xd3\xe4\x93\x02#\"!/injective/peggy/v1/request_batch\x12\x8b\x01\n\x0c\x43onfirmBatch\x12#.injective.peggy.v1.MsgConfirmBatch\x1a+.injective.peggy.v1.MsgConfirmBatchResponse\")\x82\xd3\xe4\x93\x02#\"!/injective/peggy/v1/confirm_batch\x12\x8b\x01\n\x0c\x44\x65positClaim\x12#.injective.peggy.v1.MsgDepositClaim\x1a+.injective.peggy.v1.MsgDepositClaimResponse\")\x82\xd3\xe4\x93\x02#\"!/injective/peggy/v1/deposit_claim\x12\x8f\x01\n\rWithdrawClaim\x12$.injective.peggy.v1.MsgWithdrawClaim\x1a,.injective.peggy.v1.MsgWithdrawClaimResponse\"*\x82\xd3\xe4\x93\x02$\"\"/injective/peggy/v1/withdraw_claim\x12\xa3\x01\n\x11ValsetUpdateClaim\x12).injective.peggy.v1.MsgValsetUpdatedClaim\x1a\x31.injective.peggy.v1.MsgValsetUpdatedClaimResponse\"0\x82\xd3\xe4\x93\x02*\"(/injective/peggy/v1/valset_updated_claim\x12\xa4\x01\n\x12\x45RC20DeployedClaim\x12).injective.peggy.v1.MsgERC20DeployedClaim\x1a\x31.injective.peggy.v1.MsgERC20DeployedClaimResponse\"0\x82\xd3\xe4\x93\x02*\"(/injective/peggy/v1/erc20_deployed_claim\x12\xba\x01\n\x18SetOrchestratorAddresses\x12/.injective.peggy.v1.MsgSetOrchestratorAddresses\x1a\x37.injective.peggy.v1.MsgSetOrchestratorAddressesResponse\"4\x82\xd3\xe4\x93\x02.\",/injective/peggy/v1/set_orchestrator_address\x12\x99\x01\n\x0f\x43\x61ncelSendToEth\x12&.injective.peggy.v1.MsgCancelSendToEth\x1a..injective.peggy.v1.MsgCancelSendToEthResponse\".\x82\xd3\xe4\x93\x02(\"&/injective/peggy/v1/cancel_send_to_eth\x12\xc5\x01\n\x1aSubmitBadSignatureEvidence\x12\x31.injective.peggy.v1.MsgSubmitBadSignatureEvidence\x1a\x39.injective.peggy.v1.MsgSubmitBadSignatureEvidenceResponse\"9\x82\xd3\xe4\x93\x02\x33\"1/injective/peggy/v1/submit_bad_signature_evidence\x12`\n\x0cUpdateParams\x12#.injective.peggy.v1.MsgUpdateParams\x1a+.injective.peggy.v1.MsgUpdateParamsResponse\x12\x8a\x01\n\x1a\x42lacklistEthereumAddresses\x12\x31.injective.peggy.v1.MsgBlacklistEthereumAddresses\x1a\x39.injective.peggy.v1.MsgBlacklistEthereumAddressesResponse\x12\x81\x01\n\x17RevokeEthereumBlacklist\x12..injective.peggy.v1.MsgRevokeEthereumBlacklist\x1a\x36.injective.peggy.v1.MsgRevokeEthereumBlacklistResponse\x1a\x05\x80\xe7\xb0*\x01\x42\xda\x01\n\x16\x63om.injective.peggy.v1B\tMsgsProtoP\x01ZKgithub.com/InjectiveLabs/injective-core/injective-chain/modules/peggy/types\xa2\x02\x03IPX\xaa\x02\x12Injective.Peggy.V1\xca\x02\x12Injective\\Peggy\\V1\xe2\x02\x1eInjective\\Peggy\\V1\\GPBMetadata\xea\x02\x14Injective::Peggy::V1b\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dinjective/peggy/v1/msgs.proto\x12\x12injective.peggy.v1\x1a\x14gogoproto/gogo.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x19google/protobuf/any.proto\x1a\x11\x61mino/amino.proto\x1a\x1e\x63osmos/base/v1beta1/coin.proto\x1a\x17\x63osmos/msg/v1/msg.proto\x1a\x19\x63osmos_proto/cosmos.proto\x1a\x1einjective/peggy/v1/types.proto\x1a\x1finjective/peggy/v1/params.proto\x1a#injective/peggy/v1/rate_limit.proto\"\xad\x01\n\x1bMsgSetOrchestratorAddresses\x12\x16\n\x06sender\x18\x01 \x01(\tR\x06sender\x12\"\n\x0corchestrator\x18\x02 \x01(\tR\x0corchestrator\x12\x1f\n\x0b\x65th_address\x18\x03 \x01(\tR\nethAddress:1\x82\xe7\xb0*\x06sender\x8a\xe7\xb0*!peggy/MsgSetOrchestratorAddresses\"%\n#MsgSetOrchestratorAddressesResponse\"\xb9\x01\n\x10MsgValsetConfirm\x12\x14\n\x05nonce\x18\x01 \x01(\x04R\x05nonce\x12\"\n\x0corchestrator\x18\x02 \x01(\tR\x0corchestrator\x12\x1f\n\x0b\x65th_address\x18\x03 \x01(\tR\nethAddress\x12\x1c\n\tsignature\x18\x04 \x01(\tR\tsignature:,\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x16peggy/MsgValsetConfirm\"\x1a\n\x18MsgValsetConfirmResponse\"\xde\x01\n\x0cMsgSendToEth\x12\x16\n\x06sender\x18\x01 \x01(\tR\x06sender\x12\x19\n\x08\x65th_dest\x18\x02 \x01(\tR\x07\x65thDest\x12\x37\n\x06\x61mount\x18\x03 \x01(\x0b\x32\x19.cosmos.base.v1beta1.CoinB\x04\xc8\xde\x1f\x00R\x06\x61mount\x12>\n\nbridge_fee\x18\x04 \x01(\x0b\x32\x19.cosmos.base.v1beta1.CoinB\x04\xc8\xde\x1f\x00R\tbridgeFee:\"\x82\xe7\xb0*\x06sender\x8a\xe7\xb0*\x12peggy/MsgSendToEth\"\x16\n\x14MsgSendToEthResponse\"x\n\x0fMsgRequestBatch\x12\"\n\x0corchestrator\x18\x01 \x01(\tR\x0corchestrator\x12\x14\n\x05\x64\x65nom\x18\x02 \x01(\tR\x05\x64\x65nom:+\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x15peggy/MsgRequestBatch\"\x19\n\x17MsgRequestBatchResponse\"\xdc\x01\n\x0fMsgConfirmBatch\x12\x14\n\x05nonce\x18\x01 \x01(\x04R\x05nonce\x12%\n\x0etoken_contract\x18\x02 \x01(\tR\rtokenContract\x12\x1d\n\neth_signer\x18\x03 \x01(\tR\tethSigner\x12\"\n\x0corchestrator\x18\x04 \x01(\tR\x0corchestrator\x12\x1c\n\tsignature\x18\x05 \x01(\tR\tsignature:+\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x15peggy/MsgConfirmBatch\"\x19\n\x17MsgConfirmBatchResponse\"\xea\x02\n\x0fMsgDepositClaim\x12\x1f\n\x0b\x65vent_nonce\x18\x01 \x01(\x04R\neventNonce\x12!\n\x0c\x62lock_height\x18\x02 \x01(\x04R\x0b\x62lockHeight\x12%\n\x0etoken_contract\x18\x03 \x01(\tR\rtokenContract\x12\x35\n\x06\x61mount\x18\x04 \x01(\tB\x1d\xc8\xde\x1f\x00\xda\xde\x1f\x15\x63osmossdk.io/math.IntR\x06\x61mount\x12\'\n\x0f\x65thereum_sender\x18\x05 \x01(\tR\x0e\x65thereumSender\x12\'\n\x0f\x63osmos_receiver\x18\x06 \x01(\tR\x0e\x63osmosReceiver\x12\"\n\x0corchestrator\x18\x07 \x01(\tR\x0corchestrator\x12\x12\n\x04\x64\x61ta\x18\x08 \x01(\tR\x04\x64\x61ta:+\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x15peggy/MsgDepositClaim\"\x19\n\x17MsgDepositClaimResponse\"\xf0\x01\n\x10MsgWithdrawClaim\x12\x1f\n\x0b\x65vent_nonce\x18\x01 \x01(\x04R\neventNonce\x12!\n\x0c\x62lock_height\x18\x02 \x01(\x04R\x0b\x62lockHeight\x12\x1f\n\x0b\x62\x61tch_nonce\x18\x03 \x01(\x04R\nbatchNonce\x12%\n\x0etoken_contract\x18\x04 \x01(\tR\rtokenContract\x12\"\n\x0corchestrator\x18\x05 \x01(\tR\x0corchestrator:,\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x16peggy/MsgWithdrawClaim\"\x1a\n\x18MsgWithdrawClaimResponse\"\xc4\x02\n\x15MsgERC20DeployedClaim\x12\x1f\n\x0b\x65vent_nonce\x18\x01 \x01(\x04R\neventNonce\x12!\n\x0c\x62lock_height\x18\x02 \x01(\x04R\x0b\x62lockHeight\x12!\n\x0c\x63osmos_denom\x18\x03 \x01(\tR\x0b\x63osmosDenom\x12%\n\x0etoken_contract\x18\x04 \x01(\tR\rtokenContract\x12\x12\n\x04name\x18\x05 \x01(\tR\x04name\x12\x16\n\x06symbol\x18\x06 \x01(\tR\x06symbol\x12\x1a\n\x08\x64\x65\x63imals\x18\x07 \x01(\x04R\x08\x64\x65\x63imals\x12\"\n\x0corchestrator\x18\x08 \x01(\tR\x0corchestrator:1\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x1bpeggy/MsgERC20DeployedClaim\"\x1f\n\x1dMsgERC20DeployedClaimResponse\"}\n\x12MsgCancelSendToEth\x12%\n\x0etransaction_id\x18\x01 \x01(\x04R\rtransactionId\x12\x16\n\x06sender\x18\x02 \x01(\tR\x06sender:(\x82\xe7\xb0*\x06sender\x8a\xe7\xb0*\x18peggy/MsgCancelSendToEth\"\x1c\n\x1aMsgCancelSendToEthResponse\"\xba\x01\n\x1dMsgSubmitBadSignatureEvidence\x12.\n\x07subject\x18\x01 \x01(\x0b\x32\x14.google.protobuf.AnyR\x07subject\x12\x1c\n\tsignature\x18\x02 \x01(\tR\tsignature\x12\x16\n\x06sender\x18\x03 \x01(\tR\x06sender:3\x82\xe7\xb0*\x06sender\x8a\xe7\xb0*#peggy/MsgSubmitBadSignatureEvidence\"\'\n%MsgSubmitBadSignatureEvidenceResponse\"\xfb\x02\n\x15MsgValsetUpdatedClaim\x12\x1f\n\x0b\x65vent_nonce\x18\x01 \x01(\x04R\neventNonce\x12!\n\x0cvalset_nonce\x18\x02 \x01(\x04R\x0bvalsetNonce\x12!\n\x0c\x62lock_height\x18\x03 \x01(\x04R\x0b\x62lockHeight\x12=\n\x07members\x18\x04 \x03(\x0b\x32#.injective.peggy.v1.BridgeValidatorR\x07members\x12\x42\n\rreward_amount\x18\x05 \x01(\tB\x1d\xc8\xde\x1f\x00\xda\xde\x1f\x15\x63osmossdk.io/math.IntR\x0crewardAmount\x12!\n\x0creward_token\x18\x06 \x01(\tR\x0brewardToken\x12\"\n\x0corchestrator\x18\x07 \x01(\tR\x0corchestrator:1\x82\xe7\xb0*\x0corchestrator\x8a\xe7\xb0*\x1bpeggy/MsgValsetUpdatedClaim\"\x1f\n\x1dMsgValsetUpdatedClaimResponse\"\xad\x01\n\x0fMsgUpdateParams\x12\x36\n\tauthority\x18\x01 \x01(\tB\x18\xd2\xb4-\x14\x63osmos.AddressStringR\tauthority\x12\x38\n\x06params\x18\x02 \x01(\x0b\x32\x1a.injective.peggy.v1.ParamsB\x04\xc8\xde\x1f\x00R\x06params:(\x82\xe7\xb0*\tauthority\x8a\xe7\xb0*\x15peggy/MsgUpdateParams\"\x19\n\x17MsgUpdateParamsResponse\"\x9d\x01\n\x1dMsgBlacklistEthereumAddresses\x12\x16\n\x06signer\x18\x01 \x01(\tR\x06signer\x12/\n\x13\x62lacklist_addresses\x18\x02 \x03(\tR\x12\x62lacklistAddresses:3\x82\xe7\xb0*\x06signer\x8a\xe7\xb0*#peggy/MsgBlacklistEthereumAddresses\"\'\n%MsgBlacklistEthereumAddressesResponse\"\x97\x01\n\x1aMsgRevokeEthereumBlacklist\x12\x16\n\x06signer\x18\x01 \x01(\tR\x06signer\x12/\n\x13\x62lacklist_addresses\x18\x02 \x03(\tR\x12\x62lacklistAddresses:0\x82\xe7\xb0*\x06signer\x8a\xe7\xb0* peggy/MsgRevokeEthereumBlacklist\"$\n\"MsgRevokeEthereumBlacklistResponse\"\xb1\x03\n\x12MsgCreateRateLimit\x12\x36\n\tauthority\x18\x01 \x01(\tB\x18\xd2\xb4-\x14\x63osmos.AddressStringR\tauthority\x12#\n\rtoken_address\x18\x02 \x01(\tR\x0ctokenAddress\x12%\n\x0etoken_decimals\x18\x03 \x01(\rR\rtokenDecimals\x12$\n\x0etoken_price_id\x18\x04 \x01(\tR\x0ctokenPriceId\x12I\n\x0erate_limit_usd\x18\x05 \x01(\tB#\xc8\xde\x1f\x00\xda\xde\x1f\x1b\x63osmossdk.io/math.LegacyDecR\x0crateLimitUsd\x12M\n\x13\x61\x62solute_mint_limit\x18\x06 \x01(\tB\x1d\xc8\xde\x1f\x00\xda\xde\x1f\x15\x63osmossdk.io/math.IntR\x11\x61\x62soluteMintLimit\x12*\n\x11rate_limit_window\x18\x07 \x01(\x04R\x0frateLimitWindow:+\x82\xe7\xb0*\tauthority\x8a\xe7\xb0*\x18peggy/MsgCreateRateLimit\"\x1c\n\x1aMsgCreateRateLimitResponse\"\xd0\x02\n\x12MsgUpdateRateLimit\x12\x36\n\tauthority\x18\x01 \x01(\tB\x18\xd2\xb4-\x14\x63osmos.AddressStringR\tauthority\x12#\n\rtoken_address\x18\x02 \x01(\tR\x0ctokenAddress\x12+\n\x12new_token_price_id\x18\x03 \x01(\tR\x0fnewTokenPriceId\x12P\n\x12new_rate_limit_usd\x18\x04 \x01(\tB#\xc8\xde\x1f\x00\xda\xde\x1f\x1b\x63osmossdk.io/math.LegacyDecR\x0fnewRateLimitUsd\x12\x31\n\x15new_rate_limit_window\x18\x05 \x01(\x04R\x12newRateLimitWindow:+\x82\xe7\xb0*\tauthority\x8a\xe7\xb0*\x18peggy/MsgUpdateRateLimit\"\x1c\n\x1aMsgUpdateRateLimitResponse\"\x9e\x01\n\x12MsgRemoveRateLimit\x12\x36\n\tauthority\x18\x01 \x01(\tB\x18\xd2\xb4-\x14\x63osmos.AddressStringR\tauthority\x12#\n\rtoken_address\x18\x02 \x01(\tR\x0ctokenAddress:+\x82\xe7\xb0*\tauthority\x8a\xe7\xb0*\x18peggy/MsgRemoveRateLimit\"\x1c\n\x1aMsgRemoveRateLimitResponse2\xff\x12\n\x03Msg\x12\x8f\x01\n\rValsetConfirm\x12$.injective.peggy.v1.MsgValsetConfirm\x1a,.injective.peggy.v1.MsgValsetConfirmResponse\"*\x82\xd3\xe4\x93\x02$\"\"/injective/peggy/v1/valset_confirm\x12\x80\x01\n\tSendToEth\x12 .injective.peggy.v1.MsgSendToEth\x1a(.injective.peggy.v1.MsgSendToEthResponse\"\'\x82\xd3\xe4\x93\x02!\"\x1f/injective/peggy/v1/send_to_eth\x12\x8b\x01\n\x0cRequestBatch\x12#.injective.peggy.v1.MsgRequestBatch\x1a+.injective.peggy.v1.MsgRequestBatchResponse\")\x82\xd3\xe4\x93\x02#\"!/injective/peggy/v1/request_batch\x12\x8b\x01\n\x0c\x43onfirmBatch\x12#.injective.peggy.v1.MsgConfirmBatch\x1a+.injective.peggy.v1.MsgConfirmBatchResponse\")\x82\xd3\xe4\x93\x02#\"!/injective/peggy/v1/confirm_batch\x12\x8b\x01\n\x0c\x44\x65positClaim\x12#.injective.peggy.v1.MsgDepositClaim\x1a+.injective.peggy.v1.MsgDepositClaimResponse\")\x82\xd3\xe4\x93\x02#\"!/injective/peggy/v1/deposit_claim\x12\x8f\x01\n\rWithdrawClaim\x12$.injective.peggy.v1.MsgWithdrawClaim\x1a,.injective.peggy.v1.MsgWithdrawClaimResponse\"*\x82\xd3\xe4\x93\x02$\"\"/injective/peggy/v1/withdraw_claim\x12\xa3\x01\n\x11ValsetUpdateClaim\x12).injective.peggy.v1.MsgValsetUpdatedClaim\x1a\x31.injective.peggy.v1.MsgValsetUpdatedClaimResponse\"0\x82\xd3\xe4\x93\x02*\"(/injective/peggy/v1/valset_updated_claim\x12\xa4\x01\n\x12\x45RC20DeployedClaim\x12).injective.peggy.v1.MsgERC20DeployedClaim\x1a\x31.injective.peggy.v1.MsgERC20DeployedClaimResponse\"0\x82\xd3\xe4\x93\x02*\"(/injective/peggy/v1/erc20_deployed_claim\x12\xba\x01\n\x18SetOrchestratorAddresses\x12/.injective.peggy.v1.MsgSetOrchestratorAddresses\x1a\x37.injective.peggy.v1.MsgSetOrchestratorAddressesResponse\"4\x82\xd3\xe4\x93\x02.\",/injective/peggy/v1/set_orchestrator_address\x12\x99\x01\n\x0f\x43\x61ncelSendToEth\x12&.injective.peggy.v1.MsgCancelSendToEth\x1a..injective.peggy.v1.MsgCancelSendToEthResponse\".\x82\xd3\xe4\x93\x02(\"&/injective/peggy/v1/cancel_send_to_eth\x12\xc5\x01\n\x1aSubmitBadSignatureEvidence\x12\x31.injective.peggy.v1.MsgSubmitBadSignatureEvidence\x1a\x39.injective.peggy.v1.MsgSubmitBadSignatureEvidenceResponse\"9\x82\xd3\xe4\x93\x02\x33\"1/injective/peggy/v1/submit_bad_signature_evidence\x12`\n\x0cUpdateParams\x12#.injective.peggy.v1.MsgUpdateParams\x1a+.injective.peggy.v1.MsgUpdateParamsResponse\x12\x8a\x01\n\x1a\x42lacklistEthereumAddresses\x12\x31.injective.peggy.v1.MsgBlacklistEthereumAddresses\x1a\x39.injective.peggy.v1.MsgBlacklistEthereumAddressesResponse\x12\x81\x01\n\x17RevokeEthereumBlacklist\x12..injective.peggy.v1.MsgRevokeEthereumBlacklist\x1a\x36.injective.peggy.v1.MsgRevokeEthereumBlacklistResponse\x12i\n\x0f\x43reateRateLimit\x12&.injective.peggy.v1.MsgCreateRateLimit\x1a..injective.peggy.v1.MsgCreateRateLimitResponse\x12i\n\x0fUpdateRateLimit\x12&.injective.peggy.v1.MsgUpdateRateLimit\x1a..injective.peggy.v1.MsgUpdateRateLimitResponse\x12i\n\x0fRemoveRateLimit\x12&.injective.peggy.v1.MsgRemoveRateLimit\x1a..injective.peggy.v1.MsgRemoveRateLimitResponse\x1a\x05\x80\xe7\xb0*\x01\x42\xda\x01\n\x16\x63om.injective.peggy.v1B\tMsgsProtoP\x01ZKgithub.com/InjectiveLabs/injective-core/injective-chain/modules/peggy/types\xa2\x02\x03IPX\xaa\x02\x12Injective.Peggy.V1\xca\x02\x12Injective\\Peggy\\V1\xe2\x02\x1eInjective\\Peggy\\V1\\GPBMetadata\xea\x02\x14Injective::Peggy::V1b\x06proto3')
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 | 🔴 Critical

🧩 Analysis chain

Descriptor updated to include rate_limit.proto; verify runtime deps match generator.
Ensure runtime protobuf >= the generator’s “Protobuf Python Version: 5.26.1” and grpcio is pinned compatibly across the project.


🏁 Script executed:

#!/bin/bash
# Check declared protobuf/grpc pins in repo
rg -n "protobuf|grpcio" pyproject.toml setup.cfg setup.py requirements*.txt -S -n || true

Length of output: 263


Pin grpcio and grpcio-tools to versions compatible with protobuf ^5.26.1.

In pyproject.toml, grpcio >= 1.63.0 and protobuf 5.26.1 are confirmed compatible. However, grpcio = "*" and grpcio-tools = "*" remain unpinned, allowing any version (including incompatible ones). With protobuf ^5.26.1 pinned but grpcio floating, older grpcio versions bundling incompatible protobuf runtimes will cause failures when importing the generated msgs_pb2.py descriptor.

Update pyproject.toml:

  • grpcio = ">=1.63.0,<2.0" (or minimum compatible version from your gRPC strategy)
  • grpcio-tools = ">=1.63.0,<2.0" (pin with matching grpcio version)
🤖 Prompt for AI Agents
In pyinjective/proto/injective/peggy/v1/msgs_pb2.py around line 27, the
generated protobuf descriptor can fail at import if grpcio/grpcio-tools are left
unpinned against protobuf 5.26.1; update pyproject.toml to pin grpcio and
grpcio-tools to compatible ranges (for example grpcio = ">=1.63.0,<2.0" and
grpcio-tools = ">=1.63.0,<2.0") so the runtime bundled protobuf is compatible
with protobuf ^5.26.1, then reinstall/update dependencies and regenerate/rebuild
the Python protobuf artifacts if necessary.

@socket-security
Copy link

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedckzg@​2.1.4 ⏵ 2.1.510010090100100
Addedclick@​8.3.096100100100100
Updatedcharset-normalizer@​3.4.3 ⏵ 3.4.499100100100100
Updatedcertifi@​2025.8.3 ⏵ 2025.10.510010010010070
Addedcoincurve@​18.0.0100100100100100
Addedcoincurve@​20.0.0100100100100100
Updatedattrs@​25.3.0 ⏵ 25.4.0100 +1100100100100
Updatedbitarray@​3.7.1 ⏵ 3.8.0100 +7100100100100

View full report

@aarmoa aarmoa merged commit 8645426 into dev Nov 10, 2025
9 of 10 checks passed
@aarmoa aarmoa deleted the cp-652/update_protos_for_v1_17_0 branch November 10, 2025 14:52
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)
pyinjective/proto/exchange/injective_archiver_rpc_pb2.py (1)

1-24: Tighten version constraints for grpcio and grpcio-tools in pyproject.toml.

The review comment is valid. Current dependencies in pyproject.toml show grpcio = "*" and grpcio-tools = "*" (unconstrained), while protobuf = "^5.26.1" is properly pinned. To ensure compatibility and avoid potential runtime API mismatches with the generated protobuf code, constrain grpcio and grpcio-tools as recommended:

  • grpcio = ">=1.56,<2"
  • grpcio-tools = ">=1.56,<2"

This prevents very old incompatible versions from being resolved while the protobuf constraint remains locked at ^5.26.1.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4d134c8 and 74bd9d2.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (14)
  • CHANGELOG.md (1 hunks)
  • Makefile (1 hunks)
  • buf.gen.yaml (1 hunks)
  • pyinjective/proto/exchange/injective_accounts_rpc_pb2.py (2 hunks)
  • pyinjective/proto/exchange/injective_archiver_rpc_pb2.py (2 hunks)
  • pyinjective/proto/exchange/injective_auction_rpc_pb2.py (2 hunks)
  • pyinjective/proto/exchange/injective_auction_rpc_pb2_grpc.py (4 hunks)
  • pyinjective/proto/exchange/injective_derivative_exchange_rpc_pb2.py (2 hunks)
  • pyinjective/proto/exchange/injective_explorer_rpc_pb2.py (2 hunks)
  • pyinjective/proto/exchange/injective_explorer_rpc_pb2_grpc.py (4 hunks)
  • pyinjective/proto/exchange/injective_megavault_rpc_pb2.py (2 hunks)
  • pyinjective/proto/exchange/injective_portfolio_rpc_pb2.py (2 hunks)
  • pyinjective/proto/injective/exchange/v1beta1/exchange_pb2.py (4 hunks)
  • pyinjective/proto/injective/exchange/v2/market_pb2.py (4 hunks)
✅ Files skipped from review due to trivial changes (1)
  • pyinjective/proto/exchange/injective_accounts_rpc_pb2.py
🧰 Additional context used
🪛 Ruff (0.14.3)
pyinjective/proto/exchange/injective_auction_rpc_pb2_grpc.py

113-113: Unused method argument: request

(ARG002)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Socket Security: Pull Request Alerts
🔇 Additional comments (20)
pyinjective/proto/exchange/injective_megavault_rpc_pb2.py (1)

1-95: Generated protobuf file—LGTM.

This file is auto-generated by the protocol buffer compiler. The updated byte offsets in the descriptor metadata are consistent with the proto schema changes for the v1.17.0 upgrade. No manual review of generated code is necessary.

pyinjective/proto/injective/exchange/v2/market_pb2.py (1)

1-148: LGTM! Generated protobuf code looks correct.

This is auto-generated code from the protobuf compiler, and the additions for OpenNotionalCap types and their integration into BinaryOptionsMarket and DerivativeMarket follow the expected patterns. The serialization indices have been updated consistently, and the new field options are properly configured.

pyinjective/proto/exchange/injective_auction_rpc_pb2.py (1)

17-76: LGTM! Generated code updates are consistent with proto definition changes.

The descriptor metadata and serialization offset updates are expected when regenerating protocol buffer bindings after updating proto definitions to v1.17.0. No public API surface changes are present in this file.

pyinjective/proto/exchange/injective_auction_rpc_pb2_grpc.py (4)

53-57: LGTM! AuctionsStats RPC client binding added correctly.

The new client stub method follows the established pattern and correctly wires the request/response serializers for the AuctionsStats RPC.


113-118: LGTM! AuctionsStats servicer method added correctly.

The servicer method stub is properly implemented with the standard UNIMPLEMENTED default. The static analysis warning about the unused request parameter is a false positive—servicer method signatures must match the interface even when unimplemented.


158-162: LGTM! AuctionsStats handler registration is correct.

The server-side handler correctly registers the AuctionsStats method with appropriate deserializer/serializer configuration.


364-389: LGTM! Experimental AuctionsStats client method added correctly.

The experimental client method mirrors the existing RPC helpers and correctly configures the unary_unary call with the AuctionsStats path and serializers.

pyinjective/proto/injective/exchange/v1beta1/exchange_pb2.py (4)

67-78: LGTM! OpenNotionalCap metadata properly configured.

The loaded and serialized options for the three new message types (OpenNotionalCap, OpenNotionalCapUncapped, OpenNotionalCapCapped) follow the expected cosmos-sdk patterns with proper amino serialization annotations.


141-142: LGTM! DerivativeMarket field integration looks correct.

The open_notional_cap field has been properly added to the DerivativeMarket message with appropriate serialization options.


319-438: Descriptor indices updated correctly.

The global descriptor start/end indices have been systematically updated to accommodate the three new OpenNotionalCap message types. This is the expected behavior from the protocol buffer compiler.


21-21: Let me check if the buf.gen.yaml file was modified in this PR:

File is correctly auto-generated from protobuf definitions.

The changes in this auto-generated file are consistent with the proto upgrade. The Makefile confirms proto generation is reproducible via make gen-client, and buf.gen.yaml is properly configured to pull from injective-core. Verify the buf.gen.yaml version tag (currently v1.17.0) matches the intended upgrade version in your PR, as the PR title references v1.17.0-beta.3.

pyinjective/proto/exchange/injective_explorer_rpc_pb2_grpc.py (1)

155-157: LGTM! Deprecation notices are clear and properly documented.

The gRPC method docstrings have been updated to indicate that GetAccountTxs, GetContractTxs, GetBlocks, and GetTxs are deprecated in favor of their V2 counterparts. The deprecation notices follow a consistent format and clearly direct users to the replacement methods.

Also applies to: 170-172, 185-187, 228-230

pyinjective/proto/exchange/injective_explorer_rpc_pb2.py (1)

78-196: Descriptor metadata updates are consistent.

The changes to _serialized_start and _serialized_end values are internal protobuf descriptor boundary adjustments resulting from upstream proto definition updates. These offsets are used by the protobuf runtime for deserialization and do not affect the public API or functional behavior.

pyinjective/proto/exchange/injective_portfolio_rpc_pb2.py (1)

46-58: Descriptor boundary realignment is appropriate.

The adjustments to descriptor boundaries for _DERIVATIVEPOSITION, portfolio request/response types, and the RPC service are internal metadata updates. These changes align with the repository-wide proto regeneration and do not modify any public API signatures or behavior.

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

30-178: Descriptor updates reflect OpenNotionalCap integration.

The extensive descriptor boundary adjustments throughout this file result from the addition of the OpenNotionalCap type to DerivativeMarketInfo (referenced at lines 39-40 in the serialized descriptor range for _OPENNOTIONALCAP). The cascading offset updates ensure all subsequent descriptor boundaries remain properly aligned. These are standard metadata-only changes from proto regeneration.

pyinjective/proto/exchange/injective_archiver_rpc_pb2.py (1)

30-33: New historical detail types properly integrated.

The addition of HistoricalDetailedBalance (lines 31-32) and HistoricalDetailedPNL (lines 43-44) introduces granular breakdown fields:

  • HistoricalDetailedBalance: Separates spot and perpetual balances
  • HistoricalDetailedPNL: Distinguishes realized PNL (rpnl) from unrealized PNL (upnl)

These new message types are properly integrated into the descriptor hierarchy, with appropriate cascading offset adjustments for all subsequent descriptors. The generation is consistent with the proto definition updates.

Also applies to: 43-44

buf.gen.yaml (2)

25-27: Configuration verified: hyperlane-cosmos entry correctly resolves proto files.

The hyperlane-cosmos entry with tag v1.0.1-inj is correctly configured. The proto subdir resolves to 22 proto files, including necessary definitions for Hyperlane/Core (proto/hyperlane/core), Warp v1 (proto/hyperlane/warp), and Post-Dispatch support (x/core/02_post_dispatch). The configuration aligns with the PR's addition of Hyperlane and Warp v1 types.


14-21: cosmos-sdk tag is valid; verify if all git_repo entries remain necessary.

The cosmos-sdk tag v0.50.14-inj exists in the remote repository and is valid. The .x suffix pattern difference (no .2/.3/.4 suffix) is intentional—cosmos-sdk uses monorepo versioning with module-specific tags, unlike the other dependencies.

However, the broader concern remains: with the Makefile now exclusively cloning injective-indexer v1.17.16, manually verify that all git_repo entries (cosmos-sdk, ibc-go, cometbft, wasmd, hyperlane-cosmos) are still necessary for proto resolution, or consolidate proto sources to reduce external dependencies and improve build consistency.

CHANGELOG.md (1)

7-9: ****

The CHANGELOG entry is accurate. Both versions match the actual configuration files: Injective core v1.17.0 (per buf.gen.yaml tag) and Indexer v1.17.16 (per Makefile clone target). The entry correctly documents the final release versions being used.

Makefile (1)

21-23: No issues found—prior review concern was based on incorrect assumption.

The original concern assumed the Makefile must pre-clone the repositories referenced in buf.gen.yaml (cosmos-sdk, ibc-go, cometbft, wasmd). However, the buf CLI dynamically fetches git_repo entries during buf generate execution, so the Makefile's simplified clean_repos is correct and intentional.

Version alignment is confirmed: both injective-core v1.17.0 (buf.gen.yaml line 28) and injective-indexer v1.17.16 (Makefile line 29) are properly aligned and documented in CHANGELOG.md. The build process is consistent and will not fail.

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