-
Notifications
You must be signed in to change notification settings - Fork 33
[CP-652] update protos for v1.17.0 upgrade #400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds 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
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
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
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
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this 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_capfield to derivative, binary options, and perpetual markets - Renamed
DenomDecimal/DenomDecimalsqueries toAuctionExchangeTransferDenomDecimal/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.
There was a problem hiding this 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, theextend-per-file-ignoresoption 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/contextare 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,<6to 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
requestyet. 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 casesUsing 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 popRename 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 endpointApply 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 + FIFOMirror 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 caseUncapped 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) — OKMirrors 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
📒 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)
| 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()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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=pyLength 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 -60Length 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 -20Length 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 -80Length 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=pyLength 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_idsfrom set{...}to list[...]. - Validate
INJECTIVE_PRIVATE_KEYis 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.
| quantity=Decimal(0.1), | ||
| margin=composer.calculate_margin( | ||
| quantity=Decimal(0.1), price=Decimal(25100), leverage=Decimal(1), is_reduce_only=False | ||
| ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
| """ | ||
| Demonstrate fetching denom min notionals using AsyncClient. | ||
| """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| """ | |
| 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.
| 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, | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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/nullLength 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.pyLength 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.
| _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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 generatorgrpcio = "*"✗ unconstrainedgrpcio-tools = "*"✗ unconstrained
Recommendation:
- Pin
grpcio >= 1.56, < 2to ensure generated code compatibility - Pin
grpcio-toolsto a compatible range (same reasoning as grpcio) - Optionally exclude generated
*_pb2.pyfiles 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.
| 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 | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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"
doneLength 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.)
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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__pb2If 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"
fiLength 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 -20Length 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/nullLength 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 -5Length 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__pb2Also 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.
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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__pb2Run 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.pypyinjective/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__pb2Apply 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.
| # -*- coding: utf-8 -*- | ||
| # Generated by the protocol buffer compiler. DO NOT EDIT! | ||
| # source: hyperlane/warp/v1/genesis.proto |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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
- grpc GitHub issue about supporting protobuf 5.26.0. [1]
- grpcio-status dependency metadata (shows protobuf >=5.26.1,<6.0dev). [2]
- Examples / packaging notes showing grpcio-tools historically constrained protobuf <5.0dev. [1][3]
- 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).
0a37ea0 to
4d134c8
Compare
There was a problem hiding this 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_messageAlso 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.v1while all other imports correctly usepyinjective.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__pb2pyinjective/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.v1instead of the package-relativepyinjective.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__pb2pyinjective/proto/hyperlane/core/v1/events_pb2.py (1)
15-16: Missing__init__.pyfiles will cause ImportError (duplicate concern).This issue was already flagged in a previous review: the imports on these lines require
__init__.pyfiles in all proto package directories to make them recognizable as Python packages. Without them, runtime imports will fail.Required
__init__.pyfiles:
pyinjective/proto/gogoproto/__init__.pypyinjective/proto/cosmos_proto/__init__.pypyinjective/proto/hyperlane/__init__.pypyinjective/proto/hyperlane/core/__init__.pypyinjective/proto/hyperlane/core/v1/__init__.pypyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2.py (2)
18-18: Broken import path fortypes_pb2(must usepyinjective.proto.hyperlane...).This will fail at runtime unless
hyperlaneis 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.protoannotation 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 useGuard 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.protoImporting 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__pb2Run to find and list all similar imports:
#!/bin/bash rg -nP '^\s*(from|import)\s+hyperlane\.' -C1 --type=pyexamples/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_pb2viafrom hyperlane.core.post_dispatch.v1 import ..., but in this repo the package lives underpyinjective.proto.hyperlane.core.post_dispatch.v1. At runtime this statement raisesModuleNotFoundError, 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__pb2pyinjective/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_positionmethod createsMsgOffsetPositionmessages, 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 whenUnpackMsgExecResponseorUnpackTransactionMessagesprocess 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
requestparams. 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 avoidhyperlane.*in generated code.Set
python_packagein the proto (or configure the generator) topyinjective.proto.hyperlane.core.interchain_security.v1so 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 resolvehyperlane.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/protoonsys.pathinpyinjective/__init__.py.
49-82: Lint noise in generated Servicer (unused args).Ruff ARG002 warnings on
request/contextare 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 forhyperlane.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_pb2must resolve; verify environment exposeshyperlane.*as importable. See earlier script.Expose
pyinjective/protoonsys.pathor adjust generator imports.
109-151: grpc feature usage: registered handlers support.Uses
server.add_registered_method_handlersand_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
ARG002onpyinjective/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
📒 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)
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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:
- All necessary proto dependencies are now available in injective-indexer v1.17.0-beta
- No other build targets or workflows reference the removed repositories
buf.gen.yamldoes 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 -20Length 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-gohttps://github.com/InjectiveLabs/wasmdhttps://github.com/InjectiveLabs/cometbfthttps://github.com/InjectiveLabs/cosmos-sdk
Additionally, PROTO_MODULES (line 12) still references modules corresponding to these removed repos (cometbft, ibc, cosmos, tendermint).
Either:
- Update
buf.gen.yamlto remove thegit_repoentries for these repositories, OR - Verify that
injective-indexerv1.17.0-beta bundles all necessary proto files and updatebuf.gen.yamlaccordingly
🤖 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
| 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) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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.pyLength 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 -20Length 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.
| # -*- 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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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.pyimports fromhyperlane.core.post_dispatch.v1 - This means protoc was given --proto_path mapping that maps to
hyperlane.*namespace, NOTpyinjective.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 usehyperlane.*
[analysis - critical]
- This is a REAL ISSUE: The import
from hyperlane.core.post_dispatch.v1will FAIL at runtime unless:- A separate
hyperlanepackage is installed with the exact same module structure - OR the pyinjective package setup.py has special namespace package configuration
- OR these modules are never actually imported (dead code)
- A separate
- The file location (
pyinjective/proto/hyperlane/...) strongly suggests the import should befrom 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 -3Length of output: 16
🏁 Script executed:
#!/bin/bash
# Check pyproject.toml for namespace package configuration and package discovery
cat ./pyproject.toml | head -100Length 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.
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 fLength 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 hyperlaneThen 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.
| 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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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)
PYLength 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 -20Length 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.
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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)
PYLength 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}")
PYLength 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 -30Length 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' || trueLength 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.tomlLength of output: 2592
Fix import paths to match vendored package structure: from hyperlane.warp.v1 → from 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
hyperlanepackage 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__.pyfiles, 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...
| @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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 || trueLength 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') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 || trueLength 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.
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this 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.tomlshowgrpcio = "*"andgrpcio-tools = "*"(unconstrained), whileprotobuf = "^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
⛔ Files ignored due to path filters (1)
poetry.lockis 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
OpenNotionalCaptypes and their integration intoBinaryOptionsMarketandDerivativeMarketfollow 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
requestparameter 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_capfield has been properly added to theDerivativeMarketmessage 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 thebuf.gen.yamlfile 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 (currentlyv1.17.0) matches the intended upgrade version in your PR, as the PR title referencesv1.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, andGetTxsare 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_startand_serialized_endvalues 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
OpenNotionalCaptype toDerivativeMarketInfo(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) andHistoricalDetailedPNL(lines 43-44) introduces granular breakdown fields:
HistoricalDetailedBalance: Separates spot and perpetual balancesHistoricalDetailedPNL: 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-cosmosentry with tagv1.0.1-injis correctly configured. Theprotosubdir 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-injexists in the remote repository and is valid. The.xsuffix pattern difference (no.2/.3/.4suffix) 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 allgit_repoentries (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, thebufCLI dynamically fetchesgit_repoentries duringbuf generateexecution, so the Makefile's simplifiedclean_reposis correct and intentional.Version alignment is confirmed: both
injective-core v1.17.0(buf.gen.yaml line 28) andinjective-indexer v1.17.16(Makefile line 29) are properly aligned and documented in CHANGELOG.md. The build process is consistent and will not fail.
Solves CP-652
Summary by CodeRabbit
New Features
Deprecations
Improvements