Conversation
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.
📝 WalkthroughWalkthroughThis 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
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
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 | 🟡 MinorRemove 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 | 🟡 MinorRemove 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 | 🟡 MinorRemove 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 | 🟡 MinorRemove 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 | 🟠 MajorValidate
INJECTIVE_PRIVATE_KEYbefore 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: Useasyncio.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: Useasyncio.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_KEYis not set,private_key_in_hexawill beNone, 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: Useasyncio.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
⛔ Files ignored due to path filters (1)
poetry.lockis excluded by!**/*.lock
📒 Files selected for processing (225)
.pre-commit-config.yamlMakefileREADME.mdbuf.gen.yamlexamples/chain_client/auction/2_MsgClaimVoucher.pyexamples/chain_client/auction/query/1_Vouchers.pyexamples/chain_client/auction/query/2_Voucher.pyexamples/chain_client/distribution/1_SetWithdrawAddress.pyexamples/chain_client/distribution/4_FundCommunityPool.pyexamples/chain_client/insurance/4_MsgClaimVoucher.pyexamples/chain_client/insurance/query/1_Vouchers.pyexamples/chain_client/insurance/query/2_Voucher.pypyinjective/__init__.pypyinjective/async_client.pypyinjective/async_client_v2.pypyinjective/client/chain/grpc/chain_grpc_auction_api.pypyinjective/client/chain/grpc/chain_grpc_auth_api.pypyinjective/client/chain/grpc/chain_grpc_authz_api.pypyinjective/client/chain/grpc/chain_grpc_bank_api.pypyinjective/client/chain/grpc/chain_grpc_distribution_api.pypyinjective/client/chain/grpc/chain_grpc_erc20_api.pypyinjective/client/chain/grpc/chain_grpc_evm_api.pypyinjective/client/chain/grpc/chain_grpc_exchange_api.pypyinjective/client/chain/grpc/chain_grpc_exchange_v2_api.pypyinjective/client/chain/grpc/chain_grpc_insurance_api.pypyinjective/client/chain/grpc/chain_grpc_permissions_api.pypyinjective/client/chain/grpc/chain_grpc_token_factory_api.pypyinjective/client/chain/grpc/chain_grpc_txfees_api.pypyinjective/client/chain/grpc/chain_grpc_wasm_api.pypyinjective/client/chain/grpc_stream/chain_grpc_chain_stream.pypyinjective/client/indexer/grpc/indexer_grpc_account_api.pypyinjective/client/indexer/grpc/indexer_grpc_auction_api.pypyinjective/client/indexer/grpc/indexer_grpc_derivative_api.pypyinjective/client/indexer/grpc/indexer_grpc_explorer_api.pypyinjective/client/indexer/grpc/indexer_grpc_insurance_api.pypyinjective/client/indexer/grpc/indexer_grpc_meta_api.pypyinjective/client/indexer/grpc/indexer_grpc_oracle_api.pypyinjective/client/indexer/grpc/indexer_grpc_portfolio_api.pypyinjective/client/indexer/grpc/indexer_grpc_spot_api.pypyinjective/client/indexer/grpc_stream/indexer_grpc_account_stream.pypyinjective/client/indexer/grpc_stream/indexer_grpc_auction_stream.pypyinjective/client/indexer/grpc_stream/indexer_grpc_derivative_stream.pypyinjective/client/indexer/grpc_stream/indexer_grpc_explorer_stream.pypyinjective/client/indexer/grpc_stream/indexer_grpc_meta_stream.pypyinjective/client/indexer/grpc_stream/indexer_grpc_oracle_stream.pypyinjective/client/indexer/grpc_stream/indexer_grpc_portfolio_stream.pypyinjective/client/indexer/grpc_stream/indexer_grpc_spot_stream.pypyinjective/composer.pypyinjective/composer_v2.pypyinjective/core/broadcaster.pypyinjective/core/gas_heuristics_gas_limit_estimator.pypyinjective/core/gas_limit_estimator.pypyinjective/core/ibc/channel/grpc/ibc_channel_grpc_api.pypyinjective/core/ibc/client/grpc/ibc_client_grpc_api.pypyinjective/core/ibc/connection/grpc/ibc_connection_grpc_api.pypyinjective/core/ibc/transfer/grpc/ibc_transfer_grpc_api.pypyinjective/core/market.pypyinjective/core/tendermint/grpc/tendermint_grpc_api.pypyinjective/core/tx/grpc/tx_grpc_api.pypyinjective/indexer_client.pypyinjective/ofac.jsonpyinjective/proto/cosmos/orm/module/v1alpha1/module_pb2.pypyinjective/proto/cosmos/orm/query/v1alpha1/query_pb2.pypyinjective/proto/cosmos/orm/query/v1alpha1/query_pb2_grpc.pypyinjective/proto/cosmos/orm/v1/orm_pb2.pypyinjective/proto/cosmos/orm/v1/orm_pb2_grpc.pypyinjective/proto/cosmos/orm/v1alpha1/schema_pb2.pypyinjective/proto/cosmos/orm/v1alpha1/schema_pb2_grpc.pypyinjective/proto/exchange/event_provider_api_pb2.pypyinjective/proto/exchange/injective_archiver_rpc_pb2.pypyinjective/proto/exchange/injective_chart_rpc_pb2.pypyinjective/proto/exchange/injective_derivative_exchange_rpc_pb2.pypyinjective/proto/exchange/injective_explorer_rpc_pb2.pypyinjective/proto/exchange/injective_rfq_rpc_pb2.pypyinjective/proto/exchange/injective_rfq_rpc_pb2_grpc.pypyinjective/proto/exchange/injective_rfqrpc_pb2.pypyinjective/proto/exchange/injective_tc_derivatives_rpc_pb2.pypyinjective/proto/exchange/injective_tc_derivatives_rpc_pb2_grpc.pypyinjective/proto/google/api/client_pb2.pypyinjective/proto/hyperlane/core/interchain_security/v1/events_pb2.pypyinjective/proto/hyperlane/core/interchain_security/v1/events_pb2_grpc.pypyinjective/proto/hyperlane/core/interchain_security/v1/genesis_pb2.pypyinjective/proto/hyperlane/core/interchain_security/v1/genesis_pb2_grpc.pypyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2.pypyinjective/proto/hyperlane/core/interchain_security/v1/query_pb2_grpc.pypyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2.pypyinjective/proto/hyperlane/core/interchain_security/v1/tx_pb2_grpc.pypyinjective/proto/hyperlane/core/interchain_security/v1/types_pb2.pypyinjective/proto/hyperlane/core/interchain_security/v1/types_pb2_grpc.pypyinjective/proto/hyperlane/core/module/v1/module_pb2.pypyinjective/proto/hyperlane/core/module/v1/module_pb2_grpc.pypyinjective/proto/hyperlane/core/post_dispatch/v1/events_pb2.pypyinjective/proto/hyperlane/core/post_dispatch/v1/events_pb2_grpc.pypyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2.pypyinjective/proto/hyperlane/core/post_dispatch/v1/genesis_pb2_grpc.pypyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2.pypyinjective/proto/hyperlane/core/post_dispatch/v1/query_pb2_grpc.pypyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2.pypyinjective/proto/hyperlane/core/post_dispatch/v1/tx_pb2_grpc.pypyinjective/proto/hyperlane/core/post_dispatch/v1/types_pb2.pypyinjective/proto/hyperlane/core/post_dispatch/v1/types_pb2_grpc.pypyinjective/proto/hyperlane/core/v1/events_pb2.pypyinjective/proto/hyperlane/core/v1/events_pb2_grpc.pypyinjective/proto/hyperlane/core/v1/genesis_pb2.pypyinjective/proto/hyperlane/core/v1/genesis_pb2_grpc.pypyinjective/proto/hyperlane/core/v1/query_pb2.pypyinjective/proto/hyperlane/core/v1/query_pb2_grpc.pypyinjective/proto/hyperlane/core/v1/tx_pb2.pypyinjective/proto/hyperlane/core/v1/tx_pb2_grpc.pypyinjective/proto/hyperlane/core/v1/types_pb2.pypyinjective/proto/hyperlane/core/v1/types_pb2_grpc.pypyinjective/proto/hyperlane/warp/module/v1/module_pb2.pypyinjective/proto/hyperlane/warp/module/v1/module_pb2_grpc.pypyinjective/proto/hyperlane/warp/v1/events_pb2.pypyinjective/proto/hyperlane/warp/v1/events_pb2_grpc.pypyinjective/proto/hyperlane/warp/v1/genesis_pb2.pypyinjective/proto/hyperlane/warp/v1/genesis_pb2_grpc.pypyinjective/proto/hyperlane/warp/v1/query_pb2.pypyinjective/proto/hyperlane/warp/v1/query_pb2_grpc.pypyinjective/proto/hyperlane/warp/v1/tx_pb2.pypyinjective/proto/hyperlane/warp/v1/tx_pb2_grpc.pypyinjective/proto/hyperlane/warp/v1/types_pb2.pypyinjective/proto/hyperlane/warp/v1/types_pb2_grpc.pypyinjective/proto/injective/auction/v1beta1/auction_pb2.pypyinjective/proto/injective/auction/v1beta1/genesis_pb2.pypyinjective/proto/injective/auction/v1beta1/query_pb2.pypyinjective/proto/injective/auction/v1beta1/query_pb2_grpc.pypyinjective/proto/injective/auction/v1beta1/tx_pb2.pypyinjective/proto/injective/auction/v1beta1/tx_pb2_grpc.pypyinjective/proto/injective/common/vouchers/v1/vouchers_pb2.pypyinjective/proto/injective/common/vouchers/v1/vouchers_pb2_grpc.pypyinjective/proto/injective/exchange/v1beta1/exchange_pb2.pypyinjective/proto/injective/exchange/v2/exchange_pb2.pypyinjective/proto/injective/insurance/v1beta1/events_pb2.pypyinjective/proto/injective/insurance/v1beta1/genesis_pb2.pypyinjective/proto/injective/insurance/v1beta1/insurance_pb2.pypyinjective/proto/injective/insurance/v1beta1/query_pb2.pypyinjective/proto/injective/insurance/v1beta1/query_pb2_grpc.pypyinjective/proto/injective/insurance/v1beta1/tx_pb2.pypyinjective/proto/injective/insurance/v1beta1/tx_pb2_grpc.pypyinjective/proto/injective/ocr/v1beta1/genesis_pb2.pypyinjective/proto/injective/ocr/v1beta1/genesis_pb2_grpc.pypyinjective/proto/injective/ocr/v1beta1/ocr_pb2.pypyinjective/proto/injective/ocr/v1beta1/ocr_pb2_grpc.pypyinjective/proto/injective/ocr/v1beta1/query_pb2.pypyinjective/proto/injective/ocr/v1beta1/query_pb2_grpc.pypyinjective/proto/injective/ocr/v1beta1/tx_pb2.pypyinjective/proto/injective/ocr/v1beta1/tx_pb2_grpc.pypyinjective/proto/injective/oracle/v1beta1/events_pb2.pypyinjective/proto/injective/oracle/v1beta1/genesis_pb2.pypyinjective/proto/injective/oracle/v1beta1/oracle_pb2.pypyinjective/proto/injective/peggy/v1/genesis_pb2.pypyinjective/proto/injective/peggy/v1/msgs_pb2.pypyinjective/proto/injective/peggy/v1/rate_limit_pb2.pypyinjective/proto/injective/permissions/v1beta1/genesis_pb2.pypyinjective/proto/injective/permissions/v1beta1/params_pb2.pypyinjective/proto/injective/permissions/v1beta1/permissions_pb2.pypyinjective/proto/injective/permissions/v1beta1/query_pb2.pypyinjective/proto/injective/txfees/v1beta1/tx_pb2.pypyinjective/proto/injective/txfees/v1beta1/txfees_pb2.pypyinjective/proto/injective/wasmx/v1/tx_pb2.pypyproject.tomltests/client/chain/grpc/configurable_auction_query_servicer.pytests/client/chain/grpc/configurable_auth_query_servicer.pytests/client/chain/grpc/configurable_authz_query_servicer.pytests/client/chain/grpc/configurable_bank_query_servicer.pytests/client/chain/grpc/configurable_distribution_query_servicer.pytests/client/chain/grpc/configurable_erc20_query_servicer.pytests/client/chain/grpc/configurable_evm_query_servicer.pytests/client/chain/grpc/configurable_exchange_query_servicer.pytests/client/chain/grpc/configurable_exchange_v2_query_servicer.pytests/client/chain/grpc/configurable_insurance_query_servicer.pytests/client/chain/grpc/configurable_permissions_query_servicer.pytests/client/chain/grpc/configurable_token_factory_query_servicer.pytests/client/chain/grpc/configurable_txfees_query_servicer.pytests/client/chain/grpc/configurable_wasm_query_servicer.pytests/client/chain/grpc/test_chain_grpc_auction_api.pytests/client/chain/grpc/test_chain_grpc_auth_api.pytests/client/chain/grpc/test_chain_grpc_authz_api.pytests/client/chain/grpc/test_chain_grpc_bank_api.pytests/client/chain/grpc/test_chain_grpc_distribution_api.pytests/client/chain/grpc/test_chain_grpc_erc20_api.pytests/client/chain/grpc/test_chain_grpc_evm_api.pytests/client/chain/grpc/test_chain_grpc_exchange_api.pytests/client/chain/grpc/test_chain_grpc_exchange_v2_api.pytests/client/chain/grpc/test_chain_grpc_insurance_api.pytests/client/chain/grpc/test_chain_grpc_permissions_api.pytests/client/chain/grpc/test_chain_grpc_token_factory_api.pytests/client/chain/grpc/test_chain_grpc_txfees_api.pytests/client/chain/grpc/test_chain_grpc_wasm_api.pytests/client/chain/stream_grpc/configurable_chain_stream_query_servicer.pytests/client/chain/stream_grpc/test_chain_grpc_chain_stream.pytests/client/indexer/configurable_account_query_servicer.pytests/client/indexer/configurable_auction_query_servicer.pytests/client/indexer/configurable_derivative_query_servicer.pytests/client/indexer/configurable_explorer_query_servicer.pytests/client/indexer/configurable_insurance_query_servicer.pytests/client/indexer/configurable_meta_query_servicer.pytests/client/indexer/configurable_oracle_query_servicer.pytests/client/indexer/configurable_portfolio_query_servicer.pytests/client/indexer/configurable_spot_query_servicer.pytests/client/indexer/grpc/test_indexer_grpc_derivative_api.pytests/client/indexer/grpc/test_indexer_grpc_explorer_api.pytests/client/indexer/stream_grpc/test_indexer_grpc_derivative_stream.pytests/core/ibc/channel/grpc/configurable_ibc_channel_query_servicer.pytests/core/ibc/channel/grpc/test_ibc_channel_grpc_api.pytests/core/ibc/client/grpc/configurable_ibc_client_query_servicer.pytests/core/ibc/client/grpc/test_ibc_client_grpc_api.pytests/core/ibc/connection/grpc/configurable_ibc_connection_query_servicer.pytests/core/ibc/connection/grpc/test_ibc_connection_grpc_api.pytests/core/ibc/transfer/grpc/configurable_ibc_transfer_query_servicer.pytests/core/ibc/transfer/grpc/test_ibc_transfer_grpc_api.pytests/core/tendermint/grpc/configurable_tendermint_query_servicer.pytests/core/test_gas_heuristics_gas_limit_estimator.pytests/core/test_gas_limit_estimator.pytests/core/test_market.pytests/core/test_message_based_transaction_fee_calculator.pytests/core/tx/grpc/configurable_tx_query_servicer.pytests/core/tx/grpc/test_tx_grpc_api.pytests/model_fixtures/markets_fixtures.pytests/rpc_fixtures/markets_fixtures.pytests/test_async_client_deprecation_warnings.pytests/test_async_client_v2_deprecation_warnings.pytests/test_composer.pytests/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
|
|
||
| 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 |
There was a problem hiding this comment.
🧩 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 50Repository: 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 -5Repository: 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 -20Repository: 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)" || trueRepository: 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 -B3Repository: InjectiveLabs/sdk-python
Length of output: 674
🏁 Script executed:
# Check README for version or compatibility information
cat README.md | head -100Repository: InjectiveLabs/sdk-python
Length of output: 2985
🏁 Script executed:
# Check CHANGELOG for version compatibility notes
cat CHANGELOG.md | head -200Repository: 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 -A2Repository: 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 -A2Repository: 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.
| @@ -1,4 +1,5 @@ | |||
| [ | |||
| "0x0330070fd38ec3bb94f58fa55d40368271e9e54a", | |||
There was a problem hiding this comment.
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")
PYAlso 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.
| _globals['_GOSETTINGS_RENAMEDSERVICESENTRY']._serialized_start=3050 | ||
| _globals['_GOSETTINGS_RENAMEDSERVICESENTRY']._serialized_end=3116 |
There was a problem hiding this comment.
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.
| from pyinjective.async_client_v2 import AsyncClient | ||
| from pyinjective.network import Network | ||
|
|
There was a problem hiding this comment.
🧩 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>&1Repository: 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.
| 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.
There was a problem hiding this comment.
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
📒 Files selected for processing (14)
pyinjective/async_client_v2.pypyinjective/client/chain/grpc/chain_grpc_auction_api.pypyinjective/client/chain/grpc_stream/chain_grpc_chain_stream.pypyinjective/composer_v2.pypyinjective/core/gas_limit_estimator.pypyproject.tomltests/client/chain/grpc/configurable_auction_query_servicer.pytests/client/chain/grpc/configurable_insurance_query_servicer.pytests/client/chain/grpc/test_chain_grpc_auction_api.pytests/client/chain/grpc/test_chain_grpc_authz_api.pytests/client/chain/grpc/test_chain_grpc_exchange_v2_api.pytests/client/chain/grpc/test_chain_grpc_insurance_api.pytests/client/chain/grpc/test_chain_grpc_permissions_api.pytests/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
| # ------------------------------ | ||
| # 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 |
There was a problem hiding this comment.
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.
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
Breaking Changes
AsyncClientfrompyinjective.async_client; import frompyinjective.async_client_v2insteadDocumentation