Skip to content

[CHORE] regenerate protos for injective-core/indexer and align v1.19.0-beta#410

Merged
aarmoa merged 2 commits intodevfrom
ic-985/create-python-sdk-final-release-for-v1190
Apr 15, 2026
Merged

[CHORE] regenerate protos for injective-core/indexer and align v1.19.0-beta#410
aarmoa merged 2 commits intodevfrom
ic-985/create-python-sdk-final-release-for-v1190

Conversation

@aarmoa
Copy link
Copy Markdown
Collaborator

@aarmoa aarmoa commented Apr 15, 2026

Regenerate Python protobuf stubs from the updated injective-core and indexer API definitions, and align the SDK (clients, composer, tests, examples) with the new message types and RPC surface.

Also refresh buf/codegen inputs where applicable, drop removed modules and legacy client surfaces that no longer exist upstream, and update dev tooling (e.g. Ruff for lint/import order) so CI and pre-commit stay green.

Solves IC-985

Summary by CodeRabbit

  • New Features

    • Added auction and insurance module query and transaction support with claim voucher operations
    • Added example scripts for auction and insurance chain operations
  • Breaking Changes

    • Removed deprecated AsyncClient from pyinjective.async_client; import from pyinjective.async_client_v2 instead
    • Removed deprecated denom decimal lookup methods
  • Documentation

    • Updated README to focus exclusively on V2 async client usage

Regenerate Python protobuf stubs from the updated injective-core and indexer
API definitions, and align the SDK (clients, composer, tests, examples) with
the new message types and RPC surface.

Also refresh buf/codegen inputs where applicable, drop removed modules and
legacy client surfaces that no longer exist upstream, and update dev tooling
(e.g. Ruff for lint/import order) so CI and pre-commit stay green.
@linear
Copy link
Copy Markdown

linear bot commented Apr 15, 2026

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 15, 2026

📝 Walkthrough

Walkthrough

This pull request consolidates the pyinjective SDK to exclusively use the V2 client and composer, removes the deprecated V1 async client, adds support for auction and insurance modules via new gRPC APIs, eliminates hyperlane-related proto files, and updates dependencies to newer versions including protobuf schema changes.

Changes

Cohort / File(s) Summary
Build & Configuration
.pre-commit-config.yaml, Makefile, buf.gen.yaml
Switched from flakeheaven/isort to ruff for linting, updated injective-indexer version to v1.18.59, updated buf proto source tags to newer revisions and commented out hyperlane-cosmos.
Documentation
README.md
Removed V1 vs V2 comparison section, now documents only V2 async client usage with simplified examples.
Core Client Removal
pyinjective/async_client.py, pyinjective/__init__.py
Deleted entire deprecated V1 AsyncClient module (~2491 lines) and removed its re-export from package init.
Core Client Enhancement
pyinjective/async_client_v2.py
Added new auction and insurance gRPC API clients with async methods for module params, vouchers, funds, and redemptions; removed deprecated denom-decimal methods.
Chain gRPC APIs
pyinjective/client/chain/grpc/chain_grpc_auction_api.py, chain_grpc_insurance_api.py, chain_grpc_exchange_api.py
Added voucher fetch methods to AuctionApi, introduced new InsuranceApi with eight query methods, deleted entire ExchangeApi implementation (~639 lines).
Broadcaster Standardization
pyinjective/core/broadcaster.py
Removed dual-type support for V1/V2 clients and composers; all factory methods and constructors now accept only V2 types.
Deprecated Modules
pyinjective/composer.py, pyinjective/core/market.py, pyinjective/indexer_client.py
Deleted entire deprecated Composer class (~1887 lines), removed SpotMarket/DerivativeMarket/BinaryOptionMarket classes (~274 lines), removed deprecated position-updates listener method.
Composer V2 Updates
pyinjective/composer_v2.py
Added msg_auction_claim_voucher and msg_insurance_claim_voucher methods for new module message construction.
Auction Module Examples
examples/chain_client/auction/2_MsgClaimVoucher.py, examples/chain_client/auction/query/1_Vouchers.py, examples/chain_client/auction/query/2_Voucher.py
Added three new example scripts demonstrating auction claim voucher transactions and voucher queries.
Insurance Module Examples
examples/chain_client/insurance/4_MsgClaimVoucher.py, examples/chain_client/insurance/query/1_Vouchers.py, examples/chain_client/insurance/query/2_Voucher.py
Added three new example scripts demonstrating insurance claim voucher transactions and voucher queries.
Import Updates
examples/chain_client/distribution/1_SetWithdrawAddress.py, examples/chain_client/distribution/4_FundCommunityPool.py
Updated AsyncClient imports from pyinjective to pyinjective.async_client_v2.
gRPC Stream Deprecation
pyinjective/client/chain/grpc_stream/chain_grpc_chain_stream.py
Added deprecation warning to stream() method, directing users to stream_v2.
Gas Estimator Updates
pyinjective/core/gas_limit_estimator.py
Switched post-only order type handling from exchange v1beta1 to v2 protobuf message definitions.
Hyperlane Proto Removals
pyinjective/proto/hyperlane/*/*/*.py
Deleted 22 hyperlane-related protobuf modules (events, genesis, query, tx, types, modules) across interchain-security, post-dispatch, core, and warp services (~3500+ lines).
ORM Proto Removals
pyinjective/proto/cosmos/orm/**/*.py
Deleted 5 cosmos ORM protobuf modules (module, query service stubs/bindings) (~200+ lines).
Auction Proto Updates
pyinjective/proto/injective/auction/v1beta1/auction_pb2.py, genesis_pb2.py, query_pb2.py, query_pb2_grpc.py, tx_pb2.py, tx_pb2_grpc.py
Added voucher support to auction module: new EventSetVoucher, updated genesis/query/tx schemas, added Vouchers/Voucher RPC methods and MsgClaimVoucher message.
Vouchers Proto
pyinjective/proto/injective/common/vouchers/v1/vouchers_pb2.py
Added new vouchers protobuf module defining AddressVoucher message type used across auction and insurance modules.
Exchange Proto Updates
pyinjective/proto/exchange/injective_archiver_rpc_pb2.py, injective_chart_rpc_pb2.py, injective_derivative_exchange_rpc_pb2.py, injective_explorer_rpc_pb2.py, event_provider_api_pb2.py
Updated embedded protobuf descriptors with schema changes including new execution type fields, oracle price flags, and repositioned field offsets.
RFQ Proto Refactoring
pyinjective/proto/exchange/injective_rfq_rpc*.py, injective_rfqrpc_pb2.py
Replaced old injective_rfqrpc_pb2 with new injective_rfq_rpc_pb2, updated gRPC service names/methods from GetOpenRequests/GetPendingQuotes to CreateConditionalOrder/ListConditionalOrders.
TC Derivatives Proto
pyinjective/proto/exchange/injective_tc_derivatives_rpc_pb2.py, injective_tc_derivatives_rpc_pb2_grpc.py
Added new TC Derivatives RPC service with eight query methods for orders, trades, and positions history/streaming.
Google API Proto
pyinjective/proto/google/api/client_pb2.py
Updated client proto descriptor with new flow control and batching configuration message types.
OFAC Compliance
pyinjective/ofac.json
Added 10 new sanctioned addresses to the OFAC blocklist.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AsyncClientV2
    participant ChainGrpcAuctionApi
    participant gRPC Chain
    User->>AsyncClientV2: fetch_auction_vouchers(denom)
    AsyncClientV2->>ChainGrpcAuctionApi: fetch_vouchers(denom)
    ChainGrpcAuctionApi->>gRPC Chain: QueryVouchersRequest
    gRPC Chain-->>ChainGrpcAuctionApi: QueryVouchersResponse
    ChainGrpcAuctionApi-->>AsyncClientV2: Dict[str, Any]
    AsyncClientV2-->>User: Vouchers
    
    User->>AsyncClientV2: msg_auction_claim_voucher(sender, denom)
    AsyncClientV2-->>User: MsgClaimVoucher
    User->>User: broadcast transaction
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 Hop and cheer, the V2 way is clear!
Old async_client hops off, hyperlane disappears,
Vouchers and insurance now take the stage,
A brand new auction chapter turns the page! 🎉

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ic-985/create-python-sdk-final-release-for-v1190

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

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

⚠️ Outside diff range comments (5)
pyinjective/client/indexer/grpc/indexer_grpc_auction_api.py (1)

17-17: ⚠️ Potential issue | 🟡 Minor

Remove redundant double assignment.

self._stub = self._stub = ... assigns the value twice to the same attribute. This appears to be a copy-paste error.

Proposed fix
-        self._stub = self._stub = exchange_auction_grpc.InjectiveAuctionRPCStub(channel)
+        self._stub = exchange_auction_grpc.InjectiveAuctionRPCStub(channel)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pyinjective/client/indexer/grpc/indexer_grpc_auction_api.py` at line 17,
Remove the redundant double assignment to self._stub; replace "self._stub =
self._stub = exchange_auction_grpc.InjectiveAuctionRPCStub(channel)" with a
single assignment using the same RHS so only self._stub is set to
exchange_auction_grpc.InjectiveAuctionRPCStub(channel) (locate the assignment
where self._stub is initialized in the constructor/initializer that references
exchange_auction_grpc.InjectiveAuctionRPCStub(channel)).
pyinjective/client/indexer/grpc/indexer_grpc_insurance_api.py (1)

17-17: ⚠️ Potential issue | 🟡 Minor

Remove redundant double assignment.

Same issue as in other indexer API files.

Proposed fix
-        self._stub = self._stub = exchange_insurance_grpc.InjectiveInsuranceRPCStub(channel)
+        self._stub = exchange_insurance_grpc.InjectiveInsuranceRPCStub(channel)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pyinjective/client/indexer/grpc/indexer_grpc_insurance_api.py` at line 17,
There is a redundant double assignment to self._stub in the initializer; replace
the duplicated assignment by assigning once: set self._stub =
exchange_insurance_grpc.InjectiveInsuranceRPCStub(channel) (locate the
assignment using the symbol self._stub and the InjectiveInsuranceRPCStub
constructor) so the stub is only assigned a single time.
pyinjective/client/indexer/grpc/indexer_grpc_explorer_api.py (1)

18-18: ⚠️ Potential issue | 🟡 Minor

Remove redundant double assignment.

Same issue as in indexer_grpc_auction_api.py - the stub is assigned twice.

Proposed fix
-        self._stub = self._stub = exchange_explorer_grpc.InjectiveExplorerRPCStub(channel)
+        self._stub = exchange_explorer_grpc.InjectiveExplorerRPCStub(channel)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pyinjective/client/indexer/grpc/indexer_grpc_explorer_api.py` at line 18,
Remove the redundant double assignment to self._stub: replace the duplicated
assignment expression "self._stub = self._stub =
exchange_explorer_grpc.InjectiveExplorerRPCStub(channel)" with a single
assignment "self._stub =
exchange_explorer_grpc.InjectiveExplorerRPCStub(channel)" in the initializer
where the stub is created (look for the _stub attribute and the call to
exchange_explorer_grpc.InjectiveExplorerRPCStub(channel)); also apply the same
one-line fix in the corresponding indexer_grpc_auction_api.py occurrence to
eliminate the duplicated assignment there as well.
pyinjective/client/indexer/grpc/indexer_grpc_oracle_api.py (1)

17-17: ⚠️ Potential issue | 🟡 Minor

Remove redundant double assignment.

Same issue as in other indexer API files.

Proposed fix
-        self._stub = self._stub = exchange_oracle_grpc.InjectiveOracleRPCStub(channel)
+        self._stub = exchange_oracle_grpc.InjectiveOracleRPCStub(channel)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pyinjective/client/indexer/grpc/indexer_grpc_oracle_api.py` at line 17, The
constructor currently assigns self._stub twice ("self._stub = self._stub =
exchange_oracle_grpc.InjectiveOracleRPCStub(channel)"); remove the redundant
assignment so only a single assignment remains (e.g., self._stub =
exchange_oracle_grpc.InjectiveOracleRPCStub(channel)) in the Indexer gRPC oracle
API class to avoid unnecessary repetition and mirror other indexer API files.
examples/chain_client/distribution/1_SetWithdrawAddress.py (1)

15-35: ⚠️ Potential issue | 🟠 Major

Validate INJECTIVE_PRIVATE_KEY before usage.

If the env var is missing, Lines 28 and 34 will fail at runtime with unclear errors. Add an explicit guard early in main().

Proposed fix
 async def main() -> None:
     dotenv.load_dotenv()
     configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
+    if not configured_private_key:
+        raise ValueError("Missing INJECTIVE_PRIVATE_KEY environment variable")
 
     # select network: local, testnet, mainnet
     network = Network.testnet()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain_client/distribution/1_SetWithdrawAddress.py` around lines 15 -
35, Check that configured_private_key (from os.getenv("INJECTIVE_PRIVATE_KEY"))
is not None or empty at the start of main() and fail fast with a clear
error/exit if missing; validate before calling
MsgBroadcasterWithPk.new_using_gas_heuristics, PrivateKey.from_hex or any usage
(e.g., throw/print a descriptive message like "INJECTIVE_PRIVATE_KEY not set"
and exit or raise ValueError) so subsequent calls to msg broadcaster creation,
PrivateKey.from_hex and pub key derivation do not error with unclear tracebacks.
🧹 Nitpick comments (8)
buf.gen.yaml (1)

25-27: Optional cleanup: remove permanently disabled Hyperlane block.

If Hyperlane is intentionally dropped long-term, deleting the commented block will reduce config drift and confusion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@buf.gen.yaml` around lines 25 - 27, Remove the permanently disabled Hyperlane
commented block in buf.gen.yaml (the three-line commented stanza containing
"git_repo: https://github.com/InjectiveLabs/hyperlane-cosmos", "tag:
v1.0.1-inj", and "subdir: proto") to avoid configuration drift and confusion;
simply delete that commented block so the file no longer contains the disabled
Hyperlane entry.
examples/chain_client/insurance/query/1_Vouchers.py (1)

17-17: Use asyncio.run(main()) for the script entrypoint.

asyncio.get_event_loop().run_until_complete(...) is the legacy pattern. asyncio.run(...) is the recommended approach for Python 3.9+, automatically handling event loop creation, cleanup, async generator finalization, and executor shutdown.

♻️ Proposed change
 if __name__ == "__main__":
-    asyncio.get_event_loop().run_until_complete(main())
+    asyncio.run(main())
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain_client/insurance/query/1_Vouchers.py` at line 17, Replace the
legacy event loop usage with asyncio.run for the script entrypoint: locate the
call to asyncio.get_event_loop().run_until_complete(main()) in the module that
defines async def main() and change it to use asyncio.run(main()) so the runtime
will create and clean up the event loop, finalize async generators, and shut
down executors correctly; ensure asyncio is imported and that the top-level
invocation remains under the module scope (not inside an already-running event
loop).
examples/chain_client/auction/2_MsgClaimVoucher.py (3)

53-54: Use asyncio.run() instead of deprecated event loop pattern.

Same issue as the insurance example - asyncio.get_event_loop().run_until_complete() is deprecated.

♻️ Suggested fix
 if __name__ == "__main__":
-    asyncio.get_event_loop().run_until_complete(main())
+    asyncio.run(main())
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain_client/auction/2_MsgClaimVoucher.py` around lines 53 - 54,
Replace the deprecated event-loop pattern used to run the async main function:
locate the module-level call that uses
asyncio.get_event_loop().run_until_complete(main()) and change it to use
asyncio.run(main()) so the program executes the async main() with the modern,
recommended API; keep the existing main() function and any exception handling
intact.

48-50: Unnecessary gas price refresh before function exit.

Same as the insurance example - these lines update the gas price but the function exits immediately after, making this dead code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain_client/auction/2_MsgClaimVoucher.py` around lines 48 - 50, The
final gas price refresh (calling client.current_chain_gas_price() and then
message_broadcaster.update_gas_price(gas_price=...)) is dead code because the
function exits immediately after; remove the three lines that compute and set
gas_price (the local gas_price assignment and the
message_broadcaster.update_gas_price(...) call) from the function (or move them
to a code path that actually continues execution) so only meaningful updates
remain — look for the gas_price variable and
message_broadcaster.update_gas_price usage in this file to locate the snippet.

14-15: Add validation for missing private key.

Same as the insurance example - early validation for the environment variable would improve the user experience.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain_client/auction/2_MsgClaimVoucher.py` around lines 14 - 15, The
script loads environment variables and reads INJECTIVE_PRIVATE_KEY into
private_key_in_hexa but does not validate it; add an early check after
dotenv.load_dotenv() to verify private_key_in_hexa is set and non-empty (using
the os.getenv call already present) and raise a clear exception or exit with an
informative message if missing so functions that rely on the private key (e.g.,
subsequent transaction signing logic) won't run with a None/empty value.
examples/chain_client/insurance/4_MsgClaimVoucher.py (3)

14-15: Add validation for missing private key.

If INJECTIVE_PRIVATE_KEY is not set, private_key_in_hexa will be None, causing a cryptic error later when passed to the broadcaster. Early validation provides a clearer error message.

🛡️ Suggested fix
     dotenv.load_dotenv()
     private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY")
+    if not private_key_in_hexa:
+        raise ValueError("INJECTIVE_PRIVATE_KEY environment variable is not set")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain_client/insurance/4_MsgClaimVoucher.py` around lines 14 - 15,
After loading env vars with dotenv.load_dotenv(), validate that
INJECTIVE_PRIVATE_KEY was provided by checking the variable private_key_in_hexa
and if it's None or empty emit a clear error and exit (e.g., raise RuntimeError
or print and sys.exit) before it is passed to the broadcaster; update the
top-level flow where private_key_in_hexa is used so callers (or the script)
cannot proceed without a valid key.

48-50: Unnecessary gas price refresh before function exit.

These lines fetch and update the gas price but the function immediately returns, so the updated value is never used. Consider removing this dead code or adding a comment explaining if this is intentional as a template pattern for users to extend.

♻️ Suggested fix - remove unused code
     result = await message_broadcaster.broadcast([message])
     print("---Transaction Response---")
     print(json.dumps(result, indent=2))
-
-    gas_price = await client.current_chain_gas_price()
-    gas_price = int(gas_price * 1.1)
-    message_broadcaster.update_gas_price(gas_price=gas_price)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain_client/insurance/4_MsgClaimVoucher.py` around lines 48 - 50,
The snippet fetches and updates gas price using client.current_chain_gas_price()
and message_broadcaster.update_gas_price(gas_price=...) immediately before
returning, but the updated value is never used; remove those three lines (the
gas_price assignment, scaling, and update_gas_price call) from the function (or
if they are meant as a template/example, add a one-line comment explaining it’s
intentionally left as a pattern for users to extend) to eliminate the dead code.

53-54: Use asyncio.run() instead of deprecated event loop pattern.

asyncio.get_event_loop().run_until_complete() is deprecated since Python 3.10. The modern approach is simpler and avoids deprecation warnings.

♻️ Suggested fix
 if __name__ == "__main__":
-    asyncio.get_event_loop().run_until_complete(main())
+    asyncio.run(main())
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/chain_client/insurance/4_MsgClaimVoucher.py` around lines 53 - 54,
The script currently starts the async program with
asyncio.get_event_loop().run_until_complete(main()), which is deprecated; update
the entrypoint to use asyncio.run(main()) instead by replacing that call in the
__main__ block (the invocation of main()) with asyncio.run(main()) to avoid
deprecation warnings and simplify execution.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.pre-commit-config.yaml:
- Around line 9-13: Update ruff configuration to re-enable isort checks by
adding "I" to the select list in ruff.toml and removing any ignore of "I001":
edit ruff.toml (look for the "select" array and the "ignore" or
"per-file-ignores" entries) to include "I" among the selected codes and delete
or stop ignoring "I001" so Ruff enforces import-order rules previously provided
by isort.

In `@Makefile`:
- Line 29: The Makefile clones injective-indexer at v1.18.59 which mismatches
the proto generation using injective-core v1.19.0-beta (buf.gen.yaml); update
the indexer pin in the Makefile (the git clone line that references
injective-indexer) to a matching v1.19.x tag (or the exact
v1.19.0-beta-compatible release) to ensure RPC/message compatibility, or add a
clear comment in the Makefile explaining why the older indexer pin is
intentionally kept and provide compatibility notes referencing buf.gen.yaml.

In `@pyinjective/ofac.json`:
- Line 2: Add a CI validation job named "ofac-validation" that reads
pyinjective/ofac.json and fails on parse errors, malformed addresses, or
case-insensitive duplicates: implement a script (e.g., verify_ofac_list) that
(1) json.loads the file, (2) asserts the root is a list, (3) validates every
entry against the regex ^0x[a-fA-F0-9]{40}$, (4) normalizes entries to lowercase
and checks for duplicates, and (5) exits non‑zero with clear error output if any
checks fail; wire this script into your CI (for example as a GitHub Actions step
in .github/workflows/validate-ofac.yml) so PRs touching pyinjective/ofac.json
are blocked until the list passes validation.

In `@pyinjective/proto/google/api/client_pb2.py`:
- Around line 74-75: The _GOSETTINGS_RENAMEDSERVICESENTRY descriptor currently
reuses the 3050-3116 offsets (same as _DOTNETSETTINGS_RENAMEDSERVICESENTRY)
which places GoSettings' nested descriptor outside its parent; update
_GOSETTINGS_RENAMEDSERVICESENTRY._serialized_start and _serialized_end so they
fall within the GoSettings parent range (3264-3492) and do not collide with
other descriptors, e.g., set start/end to an available subrange inside
3264-3492, then run the proto generation/consistency check to confirm the nested
GoSettings.RenamedServicesEntry is inside its parent.

In `@README.md`:
- Around line 82-84: The README V2 example imports Network from the wrong
module; update the import to use the canonical path by replacing "from
pyinjective.network import Network" with "from pyinjective.core.network import
Network" so the example matches the codebase and avoids ImportError when using
AsyncClient/Network in the V2 usage snippet.

---

Outside diff comments:
In `@examples/chain_client/distribution/1_SetWithdrawAddress.py`:
- Around line 15-35: Check that configured_private_key (from
os.getenv("INJECTIVE_PRIVATE_KEY")) is not None or empty at the start of main()
and fail fast with a clear error/exit if missing; validate before calling
MsgBroadcasterWithPk.new_using_gas_heuristics, PrivateKey.from_hex or any usage
(e.g., throw/print a descriptive message like "INJECTIVE_PRIVATE_KEY not set"
and exit or raise ValueError) so subsequent calls to msg broadcaster creation,
PrivateKey.from_hex and pub key derivation do not error with unclear tracebacks.

In `@pyinjective/client/indexer/grpc/indexer_grpc_auction_api.py`:
- Line 17: Remove the redundant double assignment to self._stub; replace
"self._stub = self._stub =
exchange_auction_grpc.InjectiveAuctionRPCStub(channel)" with a single assignment
using the same RHS so only self._stub is set to
exchange_auction_grpc.InjectiveAuctionRPCStub(channel) (locate the assignment
where self._stub is initialized in the constructor/initializer that references
exchange_auction_grpc.InjectiveAuctionRPCStub(channel)).

In `@pyinjective/client/indexer/grpc/indexer_grpc_explorer_api.py`:
- Line 18: Remove the redundant double assignment to self._stub: replace the
duplicated assignment expression "self._stub = self._stub =
exchange_explorer_grpc.InjectiveExplorerRPCStub(channel)" with a single
assignment "self._stub =
exchange_explorer_grpc.InjectiveExplorerRPCStub(channel)" in the initializer
where the stub is created (look for the _stub attribute and the call to
exchange_explorer_grpc.InjectiveExplorerRPCStub(channel)); also apply the same
one-line fix in the corresponding indexer_grpc_auction_api.py occurrence to
eliminate the duplicated assignment there as well.

In `@pyinjective/client/indexer/grpc/indexer_grpc_insurance_api.py`:
- Line 17: There is a redundant double assignment to self._stub in the
initializer; replace the duplicated assignment by assigning once: set self._stub
= exchange_insurance_grpc.InjectiveInsuranceRPCStub(channel) (locate the
assignment using the symbol self._stub and the InjectiveInsuranceRPCStub
constructor) so the stub is only assigned a single time.

In `@pyinjective/client/indexer/grpc/indexer_grpc_oracle_api.py`:
- Line 17: The constructor currently assigns self._stub twice ("self._stub =
self._stub = exchange_oracle_grpc.InjectiveOracleRPCStub(channel)"); remove the
redundant assignment so only a single assignment remains (e.g., self._stub =
exchange_oracle_grpc.InjectiveOracleRPCStub(channel)) in the Indexer gRPC oracle
API class to avoid unnecessary repetition and mirror other indexer API files.

---

Nitpick comments:
In `@buf.gen.yaml`:
- Around line 25-27: Remove the permanently disabled Hyperlane commented block
in buf.gen.yaml (the three-line commented stanza containing "git_repo:
https://github.com/InjectiveLabs/hyperlane-cosmos", "tag: v1.0.1-inj", and
"subdir: proto") to avoid configuration drift and confusion; simply delete that
commented block so the file no longer contains the disabled Hyperlane entry.

In `@examples/chain_client/auction/2_MsgClaimVoucher.py`:
- Around line 53-54: Replace the deprecated event-loop pattern used to run the
async main function: locate the module-level call that uses
asyncio.get_event_loop().run_until_complete(main()) and change it to use
asyncio.run(main()) so the program executes the async main() with the modern,
recommended API; keep the existing main() function and any exception handling
intact.
- Around line 48-50: The final gas price refresh (calling
client.current_chain_gas_price() and then
message_broadcaster.update_gas_price(gas_price=...)) is dead code because the
function exits immediately after; remove the three lines that compute and set
gas_price (the local gas_price assignment and the
message_broadcaster.update_gas_price(...) call) from the function (or move them
to a code path that actually continues execution) so only meaningful updates
remain — look for the gas_price variable and
message_broadcaster.update_gas_price usage in this file to locate the snippet.
- Around line 14-15: The script loads environment variables and reads
INJECTIVE_PRIVATE_KEY into private_key_in_hexa but does not validate it; add an
early check after dotenv.load_dotenv() to verify private_key_in_hexa is set and
non-empty (using the os.getenv call already present) and raise a clear exception
or exit with an informative message if missing so functions that rely on the
private key (e.g., subsequent transaction signing logic) won't run with a
None/empty value.

In `@examples/chain_client/insurance/4_MsgClaimVoucher.py`:
- Around line 14-15: After loading env vars with dotenv.load_dotenv(), validate
that INJECTIVE_PRIVATE_KEY was provided by checking the variable
private_key_in_hexa and if it's None or empty emit a clear error and exit (e.g.,
raise RuntimeError or print and sys.exit) before it is passed to the
broadcaster; update the top-level flow where private_key_in_hexa is used so
callers (or the script) cannot proceed without a valid key.
- Around line 48-50: The snippet fetches and updates gas price using
client.current_chain_gas_price() and
message_broadcaster.update_gas_price(gas_price=...) immediately before
returning, but the updated value is never used; remove those three lines (the
gas_price assignment, scaling, and update_gas_price call) from the function (or
if they are meant as a template/example, add a one-line comment explaining it’s
intentionally left as a pattern for users to extend) to eliminate the dead code.
- Around line 53-54: The script currently starts the async program with
asyncio.get_event_loop().run_until_complete(main()), which is deprecated; update
the entrypoint to use asyncio.run(main()) instead by replacing that call in the
__main__ block (the invocation of main()) with asyncio.run(main()) to avoid
deprecation warnings and simplify execution.

In `@examples/chain_client/insurance/query/1_Vouchers.py`:
- Line 17: Replace the legacy event loop usage with asyncio.run for the script
entrypoint: locate the call to
asyncio.get_event_loop().run_until_complete(main()) in the module that defines
async def main() and change it to use asyncio.run(main()) so the runtime will
create and clean up the event loop, finalize async generators, and shut down
executors correctly; ensure asyncio is imported and that the top-level
invocation remains under the module scope (not inside an already-running event
loop).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: efb030c0-aefb-4981-b73e-96d2a854fdbe

📥 Commits

Reviewing files that changed from the base of the PR and between 33cd59e and 726129e.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (225)
  • .pre-commit-config.yaml
  • Makefile
  • README.md
  • buf.gen.yaml
  • examples/chain_client/auction/2_MsgClaimVoucher.py
  • examples/chain_client/auction/query/1_Vouchers.py
  • examples/chain_client/auction/query/2_Voucher.py
  • examples/chain_client/distribution/1_SetWithdrawAddress.py
  • examples/chain_client/distribution/4_FundCommunityPool.py
  • examples/chain_client/insurance/4_MsgClaimVoucher.py
  • examples/chain_client/insurance/query/1_Vouchers.py
  • examples/chain_client/insurance/query/2_Voucher.py
  • pyinjective/__init__.py
  • pyinjective/async_client.py
  • pyinjective/async_client_v2.py
  • pyinjective/client/chain/grpc/chain_grpc_auction_api.py
  • pyinjective/client/chain/grpc/chain_grpc_auth_api.py
  • pyinjective/client/chain/grpc/chain_grpc_authz_api.py
  • pyinjective/client/chain/grpc/chain_grpc_bank_api.py
  • pyinjective/client/chain/grpc/chain_grpc_distribution_api.py
  • pyinjective/client/chain/grpc/chain_grpc_erc20_api.py
  • pyinjective/client/chain/grpc/chain_grpc_evm_api.py
  • pyinjective/client/chain/grpc/chain_grpc_exchange_api.py
  • pyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.py
  • pyinjective/client/chain/grpc/chain_grpc_insurance_api.py
  • pyinjective/client/chain/grpc/chain_grpc_permissions_api.py
  • pyinjective/client/chain/grpc/chain_grpc_token_factory_api.py
  • pyinjective/client/chain/grpc/chain_grpc_txfees_api.py
  • pyinjective/client/chain/grpc/chain_grpc_wasm_api.py
  • pyinjective/client/chain/grpc_stream/chain_grpc_chain_stream.py
  • pyinjective/client/indexer/grpc/indexer_grpc_account_api.py
  • pyinjective/client/indexer/grpc/indexer_grpc_auction_api.py
  • pyinjective/client/indexer/grpc/indexer_grpc_derivative_api.py
  • pyinjective/client/indexer/grpc/indexer_grpc_explorer_api.py
  • pyinjective/client/indexer/grpc/indexer_grpc_insurance_api.py
  • pyinjective/client/indexer/grpc/indexer_grpc_meta_api.py
  • pyinjective/client/indexer/grpc/indexer_grpc_oracle_api.py
  • pyinjective/client/indexer/grpc/indexer_grpc_portfolio_api.py
  • pyinjective/client/indexer/grpc/indexer_grpc_spot_api.py
  • pyinjective/client/indexer/grpc_stream/indexer_grpc_account_stream.py
  • pyinjective/client/indexer/grpc_stream/indexer_grpc_auction_stream.py
  • pyinjective/client/indexer/grpc_stream/indexer_grpc_derivative_stream.py
  • pyinjective/client/indexer/grpc_stream/indexer_grpc_explorer_stream.py
  • pyinjective/client/indexer/grpc_stream/indexer_grpc_meta_stream.py
  • pyinjective/client/indexer/grpc_stream/indexer_grpc_oracle_stream.py
  • pyinjective/client/indexer/grpc_stream/indexer_grpc_portfolio_stream.py
  • pyinjective/client/indexer/grpc_stream/indexer_grpc_spot_stream.py
  • pyinjective/composer.py
  • pyinjective/composer_v2.py
  • pyinjective/core/broadcaster.py
  • pyinjective/core/gas_heuristics_gas_limit_estimator.py
  • pyinjective/core/gas_limit_estimator.py
  • pyinjective/core/ibc/channel/grpc/ibc_channel_grpc_api.py
  • pyinjective/core/ibc/client/grpc/ibc_client_grpc_api.py
  • pyinjective/core/ibc/connection/grpc/ibc_connection_grpc_api.py
  • pyinjective/core/ibc/transfer/grpc/ibc_transfer_grpc_api.py
  • pyinjective/core/market.py
  • pyinjective/core/tendermint/grpc/tendermint_grpc_api.py
  • pyinjective/core/tx/grpc/tx_grpc_api.py
  • pyinjective/indexer_client.py
  • pyinjective/ofac.json
  • pyinjective/proto/cosmos/orm/module/v1alpha1/module_pb2.py
  • pyinjective/proto/cosmos/orm/query/v1alpha1/query_pb2.py
  • pyinjective/proto/cosmos/orm/query/v1alpha1/query_pb2_grpc.py
  • pyinjective/proto/cosmos/orm/v1/orm_pb2.py
  • pyinjective/proto/cosmos/orm/v1/orm_pb2_grpc.py
  • pyinjective/proto/cosmos/orm/v1alpha1/schema_pb2.py
  • pyinjective/proto/cosmos/orm/v1alpha1/schema_pb2_grpc.py
  • pyinjective/proto/exchange/event_provider_api_pb2.py
  • pyinjective/proto/exchange/injective_archiver_rpc_pb2.py
  • pyinjective/proto/exchange/injective_chart_rpc_pb2.py
  • pyinjective/proto/exchange/injective_derivative_exchange_rpc_pb2.py
  • pyinjective/proto/exchange/injective_explorer_rpc_pb2.py
  • pyinjective/proto/exchange/injective_rfq_rpc_pb2.py
  • pyinjective/proto/exchange/injective_rfq_rpc_pb2_grpc.py
  • pyinjective/proto/exchange/injective_rfqrpc_pb2.py
  • pyinjective/proto/exchange/injective_tc_derivatives_rpc_pb2.py
  • pyinjective/proto/exchange/injective_tc_derivatives_rpc_pb2_grpc.py
  • pyinjective/proto/google/api/client_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/events_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/events_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/genesis_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/genesis_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/types_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/types_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/module/v1/module_pb2.py
  • pyinjective/proto/hyperlane/core/module/v1/module_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/events_pb2.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/events_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/types_pb2.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/types_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/v1/events_pb2.py
  • pyinjective/proto/hyperlane/core/v1/events_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/v1/genesis_pb2.py
  • pyinjective/proto/hyperlane/core/v1/genesis_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/v1/query_pb2.py
  • pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/v1/tx_pb2.py
  • pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/v1/types_pb2.py
  • pyinjective/proto/hyperlane/core/v1/types_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/module/v1/module_pb2.py
  • pyinjective/proto/hyperlane/warp/module/v1/module_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/events_pb2.py
  • pyinjective/proto/hyperlane/warp/v1/events_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/genesis_pb2.py
  • pyinjective/proto/hyperlane/warp/v1/genesis_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/query_pb2.py
  • pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/tx_pb2.py
  • pyinjective/proto/hyperlane/warp/v1/tx_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/types_pb2.py
  • pyinjective/proto/hyperlane/warp/v1/types_pb2_grpc.py
  • pyinjective/proto/injective/auction/v1beta1/auction_pb2.py
  • pyinjective/proto/injective/auction/v1beta1/genesis_pb2.py
  • pyinjective/proto/injective/auction/v1beta1/query_pb2.py
  • pyinjective/proto/injective/auction/v1beta1/query_pb2_grpc.py
  • pyinjective/proto/injective/auction/v1beta1/tx_pb2.py
  • pyinjective/proto/injective/auction/v1beta1/tx_pb2_grpc.py
  • pyinjective/proto/injective/common/vouchers/v1/vouchers_pb2.py
  • pyinjective/proto/injective/common/vouchers/v1/vouchers_pb2_grpc.py
  • pyinjective/proto/injective/exchange/v1beta1/exchange_pb2.py
  • pyinjective/proto/injective/exchange/v2/exchange_pb2.py
  • pyinjective/proto/injective/insurance/v1beta1/events_pb2.py
  • pyinjective/proto/injective/insurance/v1beta1/genesis_pb2.py
  • pyinjective/proto/injective/insurance/v1beta1/insurance_pb2.py
  • pyinjective/proto/injective/insurance/v1beta1/query_pb2.py
  • pyinjective/proto/injective/insurance/v1beta1/query_pb2_grpc.py
  • pyinjective/proto/injective/insurance/v1beta1/tx_pb2.py
  • pyinjective/proto/injective/insurance/v1beta1/tx_pb2_grpc.py
  • pyinjective/proto/injective/ocr/v1beta1/genesis_pb2.py
  • pyinjective/proto/injective/ocr/v1beta1/genesis_pb2_grpc.py
  • pyinjective/proto/injective/ocr/v1beta1/ocr_pb2.py
  • pyinjective/proto/injective/ocr/v1beta1/ocr_pb2_grpc.py
  • pyinjective/proto/injective/ocr/v1beta1/query_pb2.py
  • pyinjective/proto/injective/ocr/v1beta1/query_pb2_grpc.py
  • pyinjective/proto/injective/ocr/v1beta1/tx_pb2.py
  • pyinjective/proto/injective/ocr/v1beta1/tx_pb2_grpc.py
  • pyinjective/proto/injective/oracle/v1beta1/events_pb2.py
  • pyinjective/proto/injective/oracle/v1beta1/genesis_pb2.py
  • pyinjective/proto/injective/oracle/v1beta1/oracle_pb2.py
  • pyinjective/proto/injective/peggy/v1/genesis_pb2.py
  • pyinjective/proto/injective/peggy/v1/msgs_pb2.py
  • pyinjective/proto/injective/peggy/v1/rate_limit_pb2.py
  • pyinjective/proto/injective/permissions/v1beta1/genesis_pb2.py
  • pyinjective/proto/injective/permissions/v1beta1/params_pb2.py
  • pyinjective/proto/injective/permissions/v1beta1/permissions_pb2.py
  • pyinjective/proto/injective/permissions/v1beta1/query_pb2.py
  • pyinjective/proto/injective/txfees/v1beta1/tx_pb2.py
  • pyinjective/proto/injective/txfees/v1beta1/txfees_pb2.py
  • pyinjective/proto/injective/wasmx/v1/tx_pb2.py
  • pyproject.toml
  • tests/client/chain/grpc/configurable_auction_query_servicer.py
  • tests/client/chain/grpc/configurable_auth_query_servicer.py
  • tests/client/chain/grpc/configurable_authz_query_servicer.py
  • tests/client/chain/grpc/configurable_bank_query_servicer.py
  • tests/client/chain/grpc/configurable_distribution_query_servicer.py
  • tests/client/chain/grpc/configurable_erc20_query_servicer.py
  • tests/client/chain/grpc/configurable_evm_query_servicer.py
  • tests/client/chain/grpc/configurable_exchange_query_servicer.py
  • tests/client/chain/grpc/configurable_exchange_v2_query_servicer.py
  • tests/client/chain/grpc/configurable_insurance_query_servicer.py
  • tests/client/chain/grpc/configurable_permissions_query_servicer.py
  • tests/client/chain/grpc/configurable_token_factory_query_servicer.py
  • tests/client/chain/grpc/configurable_txfees_query_servicer.py
  • tests/client/chain/grpc/configurable_wasm_query_servicer.py
  • tests/client/chain/grpc/test_chain_grpc_auction_api.py
  • tests/client/chain/grpc/test_chain_grpc_auth_api.py
  • tests/client/chain/grpc/test_chain_grpc_authz_api.py
  • tests/client/chain/grpc/test_chain_grpc_bank_api.py
  • tests/client/chain/grpc/test_chain_grpc_distribution_api.py
  • tests/client/chain/grpc/test_chain_grpc_erc20_api.py
  • tests/client/chain/grpc/test_chain_grpc_evm_api.py
  • tests/client/chain/grpc/test_chain_grpc_exchange_api.py
  • tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py
  • tests/client/chain/grpc/test_chain_grpc_insurance_api.py
  • tests/client/chain/grpc/test_chain_grpc_permissions_api.py
  • tests/client/chain/grpc/test_chain_grpc_token_factory_api.py
  • tests/client/chain/grpc/test_chain_grpc_txfees_api.py
  • tests/client/chain/grpc/test_chain_grpc_wasm_api.py
  • tests/client/chain/stream_grpc/configurable_chain_stream_query_servicer.py
  • tests/client/chain/stream_grpc/test_chain_grpc_chain_stream.py
  • tests/client/indexer/configurable_account_query_servicer.py
  • tests/client/indexer/configurable_auction_query_servicer.py
  • tests/client/indexer/configurable_derivative_query_servicer.py
  • tests/client/indexer/configurable_explorer_query_servicer.py
  • tests/client/indexer/configurable_insurance_query_servicer.py
  • tests/client/indexer/configurable_meta_query_servicer.py
  • tests/client/indexer/configurable_oracle_query_servicer.py
  • tests/client/indexer/configurable_portfolio_query_servicer.py
  • tests/client/indexer/configurable_spot_query_servicer.py
  • tests/client/indexer/grpc/test_indexer_grpc_derivative_api.py
  • tests/client/indexer/grpc/test_indexer_grpc_explorer_api.py
  • tests/client/indexer/stream_grpc/test_indexer_grpc_derivative_stream.py
  • tests/core/ibc/channel/grpc/configurable_ibc_channel_query_servicer.py
  • tests/core/ibc/channel/grpc/test_ibc_channel_grpc_api.py
  • tests/core/ibc/client/grpc/configurable_ibc_client_query_servicer.py
  • tests/core/ibc/client/grpc/test_ibc_client_grpc_api.py
  • tests/core/ibc/connection/grpc/configurable_ibc_connection_query_servicer.py
  • tests/core/ibc/connection/grpc/test_ibc_connection_grpc_api.py
  • tests/core/ibc/transfer/grpc/configurable_ibc_transfer_query_servicer.py
  • tests/core/ibc/transfer/grpc/test_ibc_transfer_grpc_api.py
  • tests/core/tendermint/grpc/configurable_tendermint_query_servicer.py
  • tests/core/test_gas_heuristics_gas_limit_estimator.py
  • tests/core/test_gas_limit_estimator.py
  • tests/core/test_market.py
  • tests/core/test_message_based_transaction_fee_calculator.py
  • tests/core/tx/grpc/configurable_tx_query_servicer.py
  • tests/core/tx/grpc/test_tx_grpc_api.py
  • tests/model_fixtures/markets_fixtures.py
  • tests/rpc_fixtures/markets_fixtures.py
  • tests/test_async_client_deprecation_warnings.py
  • tests/test_async_client_v2_deprecation_warnings.py
  • tests/test_composer.py
  • tests/test_composer_deprecation_warnings.py
💤 Files with no reviewable changes (58)
  • pyinjective/init.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/types_pb2_grpc.py
  • pyinjective/proto/cosmos/orm/v1/orm_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/events_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/v1/events_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/types_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/module/v1/module_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/v1/genesis_pb2_grpc.py
  • pyinjective/indexer_client.py
  • pyinjective/proto/hyperlane/core/v1/types_pb2_grpc.py
  • pyinjective/proto/cosmos/orm/v1alpha1/schema_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/module/v1/module_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/genesis_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/v1/events_pb2.py
  • pyinjective/proto/hyperlane/warp/v1/types_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/events_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/genesis_pb2.py
  • pyinjective/proto/cosmos/orm/query/v1alpha1/query_pb2.py
  • pyinjective/proto/cosmos/orm/v1/orm_pb2.py
  • pyinjective/proto/cosmos/orm/v1alpha1/schema_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/genesis_pb2_grpc.py
  • pyinjective/core/market.py
  • pyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/events_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2.py
  • pyinjective/proto/hyperlane/core/module/v1/module_pb2.py
  • pyinjective/proto/hyperlane/core/v1/genesis_pb2.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/events_pb2.py
  • pyinjective/proto/hyperlane/core/v1/types_pb2.py
  • pyinjective/proto/hyperlane/core/v1/query_pb2.py
  • pyinjective/proto/hyperlane/warp/v1/genesis_pb2.py
  • pyinjective/proto/hyperlane/warp/module/v1/module_pb2.py
  • pyinjective/proto/hyperlane/warp/v1/events_pb2.py
  • pyinjective/proto/hyperlane/warp/v1/types_pb2.py
  • pyinjective/proto/cosmos/orm/module/v1alpha1/module_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/types_pb2.py
  • pyinjective/proto/hyperlane/warp/v1/query_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/tx_pb2.py
  • pyinjective/async_client.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/types_pb2.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2.py
  • pyinjective/composer.py
  • pyinjective/proto/exchange/injective_rfqrpc_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/v1/query_pb2_grpc.py
  • pyinjective/proto/cosmos/orm/query/v1alpha1/query_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2.py
  • pyinjective/proto/hyperlane/core/interchain_security/v1/events_pb2_grpc.py
  • pyinjective/proto/hyperlane/core/v1/tx_pb2.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2.py
  • pyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2_grpc.py
  • pyinjective/proto/hyperlane/warp/v1/tx_pb2_grpc.py
  • pyinjective/client/chain/grpc/chain_grpc_exchange_api.py

Comment thread .pre-commit-config.yaml
Comment thread Makefile

clone-injective-indexer:
git clone https://github.com/InjectiveLabs/injective-indexer.git -b v1.18.3 --depth 1 --single-branch
git clone https://github.com/InjectiveLabs/injective-indexer.git -b v1.18.59 --depth 1 --single-branch
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Current Makefile pin =="
rg -n -C2 'clone-injective-indexer|injective-indexer\.git|-b v' Makefile

echo "== Remote tags check (exists + nearby versions) =="
git ls-remote --tags https://github.com/InjectiveLabs/injective-indexer.git \
  | rg -n 'refs/tags/v1\.18\.59$|refs/tags/v1\.19|refs/tags/v1\.18' \
  | tail -n 50

Repository: InjectiveLabs/sdk-python

Length of output: 502


🏁 Script executed:

# Search for references to proto versions, v1.19.0-beta, or indexer compatibility
rg -i "v1\.19|proto.*version|indexer.*version|compatibility" --type-list | head -5

Repository: InjectiveLabs/sdk-python

Length of output: 457


🏁 Script executed:

# Search for README or documentation files that might explain version requirements
find . -maxdepth 2 -type f \( -name "README*" -o -name "*.md" -o -name "requirements*" -o -name "setup.py" \) | head -20

Repository: InjectiveLabs/sdk-python

Length of output: 151


🏁 Script executed:

# Check if there are any version or compatibility files in the root
ls -la | grep -E "(version|proto|indexer|requirement)" || true

Repository: InjectiveLabs/sdk-python

Length of output: 50


🏁 Script executed:

# Search the codebase for any mentions of v1.18.59 or comments about this pin
rg "v1\.18\.59|v1\.19\.0" -A3 -B3

Repository: InjectiveLabs/sdk-python

Length of output: 674


🏁 Script executed:

# Check README for version or compatibility information
cat README.md | head -100

Repository: InjectiveLabs/sdk-python

Length of output: 2985


🏁 Script executed:

# Check CHANGELOG for version compatibility notes
cat CHANGELOG.md | head -200

Repository: InjectiveLabs/sdk-python

Length of output: 7787


🏁 Script executed:

# Search for any TODOs or FIXMEs related to versions or indexer
rg "TODO|FIXME|XXX" Makefile buf.gen.yaml -B2 -A2

Repository: InjectiveLabs/sdk-python

Length of output: 50


🏁 Script executed:

# Check if there's any documentation or comments explaining the version pin
rg "v1\.18|v1\.19|indexer" --type md -B2 -A2

Repository: InjectiveLabs/sdk-python

Length of output: 1759


Address version mismatch between proto and indexer pins.

The proto generation (buf.gen.yaml) uses v1.19.0-beta from injective-core, but the Makefile pins the indexer to v1.18.59. Based on the CHANGELOG (v1.13.0: compatibility with core v1.18.0 and indexer v1.18.3), indexer and core versions are kept closely aligned. For proto v1.19.0-beta, the indexer should likely be v1.19.x to ensure RPC/message definition compatibility. Either upgrade the indexer pin or clarify if using older indexer APIs is intentional.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Makefile` at line 29, The Makefile clones injective-indexer at v1.18.59 which
mismatches the proto generation using injective-core v1.19.0-beta
(buf.gen.yaml); update the indexer pin in the Makefile (the git clone line that
references injective-indexer) to a matching v1.19.x tag (or the exact
v1.19.0-beta-compatible release) to ensure RPC/message compatibility, or add a
clear comment in the Makefile explaining why the older indexer pin is
intentionally kept and provide compatibility notes referencing buf.gen.yaml.

Comment thread pyinjective/ofac.json
@@ -1,4 +1,5 @@
[
"0x0330070fd38ec3bb94f58fa55d40368271e9e54a",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add CI validation for OFAC address integrity before shipping.

These new entries are compliance-sensitive, but this file has no built-in guardrails for malformed or duplicate addresses. Please add an automated check (format + dedupe + normalization policy) to prevent silent screening regressions.

#!/bin/bash
# Verify OFAC address list integrity (read-only).
# Expected:
# 1) JSON parses successfully
# 2) Every entry matches 0x + 40 hex chars
# 3) No duplicates after lowercase normalization
python - <<'PY'
import json, re, sys
from collections import Counter

path = "pyinjective/ofac.json"
with open(path, "r", encoding="utf-8") as f:
    data = json.load(f)

if not isinstance(data, list):
    print("FAIL: root is not a list")
    sys.exit(1)

pat = re.compile(r"^0x[a-fA-F0-9]{40}$")
invalid = [(i+1, v) for i, v in enumerate(data) if not isinstance(v, str) or not pat.match(v)]

norm = [v.lower() for v in data if isinstance(v, str)]
dups = [k for k, c in Counter(norm).items() if c > 1]

print(f"Total entries: {len(data)}")
print(f"Invalid entries: {len(invalid)}")
if invalid:
    for ln, v in invalid[:20]:
        print(f"  line_index={ln}, value={v}")

print(f"Duplicates (case-insensitive): {len(dups)}")
if dups:
    for v in dups[:20]:
        print(f"  {v}")

if invalid or dups:
    sys.exit(2)
print("PASS")
PY

Also applies to: 43-44, 56-56, 60-60, 66-66, 71-72, 90-91

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pyinjective/ofac.json` at line 2, Add a CI validation job named
"ofac-validation" that reads pyinjective/ofac.json and fails on parse errors,
malformed addresses, or case-insensitive duplicates: implement a script (e.g.,
verify_ofac_list) that (1) json.loads the file, (2) asserts the root is a list,
(3) validates every entry against the regex ^0x[a-fA-F0-9]{40}$, (4) normalizes
entries to lowercase and checks for duplicates, and (5) exits non‑zero with
clear error output if any checks fail; wire this script into your CI (for
example as a GitHub Actions step in .github/workflows/validate-ofac.yml) so PRs
touching pyinjective/ofac.json are blocked until the list passes validation.

Comment on lines +74 to +75
_globals['_GOSETTINGS_RENAMEDSERVICESENTRY']._serialized_start=3050
_globals['_GOSETTINGS_RENAMEDSERVICESENTRY']._serialized_end=3116
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix the duplicated GoSettings.RenamedServicesEntry serialized offsets.

_GOSETTINGS_RENAMEDSERVICESENTRY is assigned the same 3050-3116 range as _DOTNETSETTINGS_RENAMEDSERVICESENTRY, but GoSettings itself lives at 3264-3492. That puts the nested Go descriptor outside its parent range, which makes the pure-Python descriptor metadata internally inconsistent.

Suggested fix
-  _globals['_GOSETTINGS_RENAMEDSERVICESENTRY']._serialized_start=3050
-  _globals['_GOSETTINGS_RENAMEDSERVICESENTRY']._serialized_end=3116
+  # Re-run protoc for this proto set; these offsets should point to the
+  # GoSettings.RenamedServicesEntry descriptor inside _GOSETTINGS.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pyinjective/proto/google/api/client_pb2.py` around lines 74 - 75, The
_GOSETTINGS_RENAMEDSERVICESENTRY descriptor currently reuses the 3050-3116
offsets (same as _DOTNETSETTINGS_RENAMEDSERVICESENTRY) which places GoSettings'
nested descriptor outside its parent; update
_GOSETTINGS_RENAMEDSERVICESENTRY._serialized_start and _serialized_end so they
fall within the GoSettings parent range (3264-3492) and do not collide with
other descriptors, e.g., set start/end to an available subrange inside
3264-3492, then run the proto generation/consistency check to confirm the nested
GoSettings.RenamedServicesEntry is inside its parent.

Comment thread README.md
Comment on lines +82 to +84
from pyinjective.async_client_v2 import AsyncClient
from pyinjective.network import Network

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Network module files:"
fd -i 'network.py'

echo "Network class definitions:"
rg -n --type=py '\bclass\s+Network\b'

echo "Current import paths used in repository:"
rg -n --type=py 'from pyinjective\.network import Network|from pyinjective\.core\.network import Network'

Repository: InjectiveLabs/sdk-python

Length of output: 35125


🏁 Script executed:

cat -n README.md | sed -n '75,95p'

Repository: InjectiveLabs/sdk-python

Length of output: 960


🏁 Script executed:

find pyinjective -name '__init__.py' -type f -exec grep -l "from.*network.*import\|Network" {} \;

Repository: InjectiveLabs/sdk-python

Length of output: 50


🏁 Script executed:

ls -la pyinjective/network.py 2>&1

Repository: InjectiveLabs/sdk-python

Length of output: 137


Fix the Network import path in the README.md V2 usage example.

Line 83 uses from pyinjective.network import Network, but this module does not exist. The correct import path is from pyinjective.core.network import Network, which is used consistently throughout the codebase and all examples. Users copying this documentation snippet will encounter an ImportError.

📝 Proposed doc fix
 from pyinjective.async_client_v2 import AsyncClient
-from pyinjective.network import Network
+from pyinjective.core.network import Network
📝 Committable suggestion

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

Suggested change
from pyinjective.async_client_v2 import AsyncClient
from pyinjective.network import Network
from pyinjective.async_client_v2 import AsyncClient
from pyinjective.core.network import Network
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 82 - 84, The README V2 example imports Network from
the wrong module; update the import to use the canonical path by replacing "from
pyinjective.network import Network" with "from pyinjective.core.network import
Network" so the example matches the codebase and avoids ImportError when using
AsyncClient/Network in the V2 usage snippet.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pyinjective/async_client_v2.py`:
- Around line 1205-1249: Add public wrappers on AsyncClient to expose the
underlying ChainGrpcAuctionApi.fetch_module_state and
ChainGrpcInsuranceApi.fetch_module_state methods: implement async def
fetch_auction_module_state(self) -> Dict[str, Any] that calls and returns await
self.auction_chain_api.fetch_module_state(), and implement async def
fetch_insurance_module_state(self) -> Dict[str, Any] that calls and returns
await self.insurance_chain_api.fetch_module_state(); place them alongside the
existing fetch_auction_module_params and fetch_insurance_module_params methods
so the regenerated RPC surface is fully exposed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3c6d520f-4ae8-42b1-80a5-7040e23b19df

📥 Commits

Reviewing files that changed from the base of the PR and between 726129e and e041678.

📒 Files selected for processing (14)
  • pyinjective/async_client_v2.py
  • pyinjective/client/chain/grpc/chain_grpc_auction_api.py
  • pyinjective/client/chain/grpc_stream/chain_grpc_chain_stream.py
  • pyinjective/composer_v2.py
  • pyinjective/core/gas_limit_estimator.py
  • pyproject.toml
  • tests/client/chain/grpc/configurable_auction_query_servicer.py
  • tests/client/chain/grpc/configurable_insurance_query_servicer.py
  • tests/client/chain/grpc/test_chain_grpc_auction_api.py
  • tests/client/chain/grpc/test_chain_grpc_authz_api.py
  • tests/client/chain/grpc/test_chain_grpc_exchange_v2_api.py
  • tests/client/chain/grpc/test_chain_grpc_insurance_api.py
  • tests/client/chain/grpc/test_chain_grpc_permissions_api.py
  • tests/client/chain/stream_grpc/test_chain_grpc_chain_stream.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • pyinjective/client/chain/grpc_stream/chain_grpc_chain_stream.py
  • pyinjective/client/chain/grpc/chain_grpc_auction_api.py
  • pyinjective/core/gas_limit_estimator.py
  • pyinjective/composer_v2.py

Comment on lines +1205 to +1249
# ------------------------------
# region Auction module (chain)

async def fetch_auction_module_params(self) -> Dict[str, Any]:
return await self.auction_chain_api.fetch_module_params()

async def fetch_current_auction_basket(self) -> Dict[str, Any]:
return await self.auction_chain_api.fetch_current_basket()

async def fetch_auction_vouchers(self, denom: str) -> Dict[str, Any]:
return await self.auction_chain_api.fetch_vouchers(denom=denom)

async def fetch_auction_voucher(self, denom: str, address: str) -> Dict[str, Any]:
return await self.auction_chain_api.fetch_voucher(denom=denom, address=address)

# endregion

# ------------------------------
# region Insurance module (chain)

async def fetch_insurance_module_params(self) -> Dict[str, Any]:
return await self.insurance_chain_api.fetch_module_params()

async def fetch_insurance_fund(self, market_id: str) -> Dict[str, Any]:
return await self.insurance_chain_api.fetch_insurance_fund(market_id=market_id)

async def fetch_insurance_funds(self) -> Dict[str, Any]:
return await self.insurance_chain_api.fetch_insurance_funds()

async def fetch_estimated_redemptions(self, market_id: str, address: str) -> Dict[str, Any]:
return await self.insurance_chain_api.fetch_estimated_redemptions(market_id=market_id, address=address)

async def fetch_pending_redemptions(self, market_id: str, address: str) -> Dict[str, Any]:
return await self.insurance_chain_api.fetch_pending_redemptions(market_id=market_id, address=address)

async def fetch_failed_redemptions(self) -> Dict[str, Any]:
return await self.insurance_chain_api.fetch_failed_redemptions()

async def fetch_insurance_vouchers(self, denom: str) -> Dict[str, Any]:
return await self.insurance_chain_api.fetch_vouchers(denom=denom)

async def fetch_insurance_voucher(self, denom: str, address: str) -> Dict[str, Any]:
return await self.insurance_chain_api.fetch_voucher(denom=denom, address=address)

# endregion
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Expose the module-state queries on AsyncClient as well.

ChainGrpcAuctionApi and ChainGrpcInsuranceApi already implement fetch_module_state(), but the new public wrappers stop short of exposing them here. That leaves part of the regenerated RPC surface unavailable from the main v2 client, even though the lower-level adapters are already in place.

Suggested patch
     async def fetch_auction_module_params(self) -> Dict[str, Any]:
         return await self.auction_chain_api.fetch_module_params()
 
+    async def fetch_auction_module_state(self) -> Dict[str, Any]:
+        return await self.auction_chain_api.fetch_module_state()
+
     async def fetch_current_auction_basket(self) -> Dict[str, Any]:
         return await self.auction_chain_api.fetch_current_basket()
@@
     async def fetch_insurance_module_params(self) -> Dict[str, Any]:
         return await self.insurance_chain_api.fetch_module_params()
 
+    async def fetch_insurance_module_state(self) -> Dict[str, Any]:
+        return await self.insurance_chain_api.fetch_module_state()
+
     async def fetch_insurance_fund(self, market_id: str) -> Dict[str, Any]:
         return await self.insurance_chain_api.fetch_insurance_fund(market_id=market_id)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pyinjective/async_client_v2.py` around lines 1205 - 1249, Add public wrappers
on AsyncClient to expose the underlying ChainGrpcAuctionApi.fetch_module_state
and ChainGrpcInsuranceApi.fetch_module_state methods: implement async def
fetch_auction_module_state(self) -> Dict[str, Any] that calls and returns await
self.auction_chain_api.fetch_module_state(), and implement async def
fetch_insurance_module_state(self) -> Dict[str, Any] that calls and returns
await self.insurance_chain_api.fetch_module_state(); place them alongside the
existing fetch_auction_module_params and fetch_insurance_module_params methods
so the regenerated RPC surface is fully exposed.

@aarmoa aarmoa merged commit b928e2e into dev Apr 15, 2026
14 checks passed
@aarmoa aarmoa deleted the ic-985/create-python-sdk-final-release-for-v1190 branch April 15, 2026 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant