Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ clean-all:
$(call clean_repos)

clone-injective-indexer:
git clone https://github.com/InjectiveLabs/injective-indexer.git -b v1.17.16 --depth 1 --single-branch
git clone https://github.com/InjectiveLabs/injective-indexer.git -b v1.17.71 --depth 1 --single-branch

clone-all: clone-injective-indexer

Expand Down
12 changes: 6 additions & 6 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ inputs:
- git_repo: https://github.com/InjectiveLabs/wasmd
tag: v0.53.3-inj.2
- git_repo: https://github.com/InjectiveLabs/cometbft
tag: v1.0.1-inj.4
tag: v1.0.1-inj.3
- git_repo: https://github.com/InjectiveLabs/cosmos-sdk
tag: v0.50.14-inj
tag: v0.50.14-inj.3
# - git_repo: https://github.com/InjectiveLabs/wasmd
# branch: v0.51.x-inj
# subdir: proto
- git_repo: https://github.com/InjectiveLabs/hyperlane-cosmos
tag: v1.0.1-inj
subdir: proto
# - git_repo: https://github.com/InjectiveLabs/injective-core
# tag: v1.17.0
# subdir: proto
- git_repo: https://github.com/InjectiveLabs/injective-core
tag: v1.17.0
branch: c-655/add_chainlink_data_streams_oracle
subdir: proto
Comment on lines +32 to 33
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Replace branch reference with tagged release or commit SHA.

Using a feature branch (c-655/add_chainlink_data_streams_oracle) for the injective-core dependency is problematic because:

  • Branch references are mutable and can change unexpectedly
  • This breaks build reproducibility
  • Not suitable for production or release candidates
  • Makes debugging and auditing difficult
🔎 Recommended fix

Use either:

  1. A tagged release once the branch is merged (preferred):
  - git_repo: https://github.com/InjectiveLabs/injective-core
-   branch: c-655/add_chainlink_data_streams_oracle
+   tag: v1.18.0  # or appropriate version
    subdir: proto
  1. A specific commit SHA for immutability:
  - git_repo: https://github.com/InjectiveLabs/injective-core
-   branch: c-655/add_chainlink_data_streams_oracle
+   commit: <full-40-char-sha>
    subdir: proto

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

🤖 Prompt for AI Agents
In buf.gen.yaml around lines 32–33, the dependency currently points to a mutable
branch (c-655/add_chainlink_data_streams_oracle); replace this with an immutable
reference by using either a released tag (preferred) or a specific commit SHA
for the injective-core dependency. Update the branch field to the chosen
immutable identifier (tag or commit SHA), regenerate any buf/lock/CI artifacts
(run your buf/bazel/npm regen or lockfile update steps) and verify builds to
ensure reproducibility.

# - git_repo: https://github.com/InjectiveLabs/injective-core
# branch: master
# subdir: proto
- directory: proto
3 changes: 2 additions & 1 deletion examples/chain_client/permissions/1_MsgCreateNamespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,13 @@ async def main() -> None:
message = composer.msg_create_namespace(
sender=address.to_acc_bech32(),
denom=denom,
contract_hook="",
wasm_hook="",
role_permissions=[role1, role2, role3],
actor_roles=[actor_role1, actor_role2],
role_managers=[role_manager],
policy_statuses=[policy_status1, policy_status2],
policy_manager_capabilities=[policy_manager_capability],
evm_hook="",
)

# broadcast the transaction
Expand Down
3 changes: 2 additions & 1 deletion examples/chain_client/permissions/2_MsgUpdateNamespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,12 @@ async def main() -> None:
message = composer.msg_update_namespace(
sender=address.to_acc_bech32(),
denom=denom,
contract_hook="inj19ld6swyldyujcn72j7ugnu9twafhs9wxlyye5m",
wasm_hook="inj19ld6swyldyujcn72j7ugnu9twafhs9wxlyye5m",
role_permissions=[role1, role2],
role_managers=[role_manager],
policy_statuses=[policy_status1, policy_status2],
policy_manager_capabilities=[policy_manager_capability],
evm_hook="",
)

# broadcast the transaction
Expand Down
2 changes: 1 addition & 1 deletion examples/exchange_client/oracle_rpc/3_OracleList.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = IndexerClient(network)
oracle_list = await client.fetch_oracle_list()
oracle_list = await client.fetch_oracle_list(symbol="TIA", oracle_type="provider")
print(json.dumps(oracle_list, indent=2))


Expand Down
401 changes: 211 additions & 190 deletions poetry.lock

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions pyinjective/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1294,8 +1294,10 @@ async def fetch_oracle_price(
oracle_scale_factor=oracle_scale_factor,
)

async def fetch_oracle_list(self) -> Dict[str, Any]:
return await self.indexer_client.fetch_oracle_list()
async def fetch_oracle_list(
self, symbol: Optional[str] = None, oracle_type: Optional[str] = None
) -> Dict[str, Any]:
return await self.indexer_client.fetch_oracle_list(symbol=symbol, oracle_type=oracle_type)

# InsuranceRPC

Expand Down
9 changes: 7 additions & 2 deletions pyinjective/client/indexer/grpc/indexer_grpc_oracle_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@ def __init__(self, channel: Channel, cookie_assistant: CookieAssistant):
self._stub = self._stub = exchange_oracle_grpc.InjectiveOracleRPCStub(channel)
self._assistant = GrpcApiRequestAssistant(cookie_assistant=cookie_assistant)

async def fetch_oracle_list(self) -> Dict[str, Any]:
request = exchange_oracle_pb.OracleListRequest()
async def fetch_oracle_list(
self, symbol: Optional[str] = None, oracle_type: Optional[str] = None
) -> Dict[str, Any]:
request = exchange_oracle_pb.OracleListRequest(
symbol=symbol,
oracle_type=oracle_type,
)
response = await self._execute_call(call=self._stub.OracleList, request=request)

return response
Expand Down
15 changes: 10 additions & 5 deletions pyinjective/composer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1626,21 +1626,23 @@ def msg_create_namespace(
self,
sender: str,
denom: str,
contract_hook: str,
wasm_hook: str,
role_permissions: List[injective_permissions_pb.Role],
actor_roles: List[injective_permissions_pb.ActorRoles],
role_managers: List[injective_permissions_pb.RoleManager],
policy_statuses: List[injective_permissions_pb.PolicyStatus],
policy_manager_capabilities: List[injective_permissions_pb.PolicyManagerCapability],
evm_hook: str,
) -> injective_permissions_tx_pb.MsgCreateNamespace:
namespace = injective_permissions_pb.Namespace(
denom=denom,
contract_hook=contract_hook,
wasm_hook=wasm_hook,
role_permissions=role_permissions,
actor_roles=actor_roles,
role_managers=role_managers,
policy_statuses=policy_statuses,
policy_manager_capabilities=policy_manager_capabilities,
evm_hook=evm_hook,
)
return injective_permissions_tx_pb.MsgCreateNamespace(
sender=sender,
Expand All @@ -1651,22 +1653,25 @@ def msg_update_namespace(
self,
sender: str,
denom: str,
contract_hook: str,
wasm_hook: str,
role_permissions: List[injective_permissions_pb.Role],
role_managers: List[injective_permissions_pb.RoleManager],
policy_statuses: List[injective_permissions_pb.PolicyStatus],
policy_manager_capabilities: List[injective_permissions_pb.PolicyManagerCapability],
evm_hook: str,
) -> injective_permissions_tx_pb.MsgUpdateNamespace:
contract_hook_update = injective_permissions_tx_pb.MsgUpdateNamespace.SetContractHook(new_value=contract_hook)
wasm_hook_update = injective_permissions_tx_pb.MsgUpdateNamespace.SetContractHook(new_value=wasm_hook)
evm_hook_update = injective_permissions_tx_pb.MsgUpdateNamespace.SetContractHook(new_value=evm_hook)

return injective_permissions_tx_pb.MsgUpdateNamespace(
sender=sender,
denom=denom,
contract_hook=contract_hook_update,
wasm_hook=wasm_hook_update,
role_permissions=role_permissions,
role_managers=role_managers,
policy_statuses=policy_statuses,
policy_manager_capabilities=policy_manager_capabilities,
evm_hook=evm_hook_update,
)

def msg_update_actor_roles(
Expand Down
15 changes: 10 additions & 5 deletions pyinjective/composer_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -1695,21 +1695,23 @@ def msg_create_namespace(
self,
sender: str,
denom: str,
contract_hook: str,
wasm_hook: str,
role_permissions: List[injective_permissions_pb.Role],
actor_roles: List[injective_permissions_pb.ActorRoles],
role_managers: List[injective_permissions_pb.RoleManager],
policy_statuses: List[injective_permissions_pb.PolicyStatus],
policy_manager_capabilities: List[injective_permissions_pb.PolicyManagerCapability],
evm_hook: str,
) -> injective_permissions_tx_pb.MsgCreateNamespace:
namespace = injective_permissions_pb.Namespace(
denom=denom,
contract_hook=contract_hook,
wasm_hook=wasm_hook,
role_permissions=role_permissions,
actor_roles=actor_roles,
role_managers=role_managers,
policy_statuses=policy_statuses,
policy_manager_capabilities=policy_manager_capabilities,
evm_hook=evm_hook,
)
return injective_permissions_tx_pb.MsgCreateNamespace(
sender=sender,
Expand All @@ -1720,22 +1722,25 @@ def msg_update_namespace(
self,
sender: str,
denom: str,
contract_hook: str,
wasm_hook: str,
role_permissions: List[injective_permissions_pb.Role],
role_managers: List[injective_permissions_pb.RoleManager],
policy_statuses: List[injective_permissions_pb.PolicyStatus],
policy_manager_capabilities: List[injective_permissions_pb.PolicyManagerCapability],
evm_hook: str,
) -> injective_permissions_tx_pb.MsgUpdateNamespace:
contract_hook_update = injective_permissions_tx_pb.MsgUpdateNamespace.SetContractHook(new_value=contract_hook)
wasm_hook_update = injective_permissions_tx_pb.MsgUpdateNamespace.SetContractHook(new_value=wasm_hook)
evm_hook_update = injective_permissions_tx_pb.MsgUpdateNamespace.SetContractHook(new_value=evm_hook)

return injective_permissions_tx_pb.MsgUpdateNamespace(
sender=sender,
denom=denom,
contract_hook=contract_hook_update,
wasm_hook=wasm_hook_update,
role_permissions=role_permissions,
role_managers=role_managers,
policy_statuses=policy_statuses,
policy_manager_capabilities=policy_manager_capabilities,
evm_hook=evm_hook_update,
)

def msg_update_actor_roles(
Expand Down
6 changes: 4 additions & 2 deletions pyinjective/indexer_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,8 +659,10 @@ def oracle_price_v2_filter(
async def fetch_oracle_price_v2(self, filters: List[exchange_oracle_pb.PricePayloadV2]) -> Dict[str, Any]:
return await self.oracle_api.fetch_oracle_price_v2(filters=filters)

async def fetch_oracle_list(self) -> Dict[str, Any]:
return await self.oracle_api.fetch_oracle_list()
async def fetch_oracle_list(
self, symbol: Optional[str] = None, oracle_type: Optional[str] = None
) -> Dict[str, Any]:
return await self.oracle_api.fetch_oracle_list(symbol=symbol, oracle_type=oracle_type)

async def listen_oracle_prices_updates(
self,
Expand Down
3 changes: 3 additions & 0 deletions pyinjective/ofac.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"0x57ec89a0c056163a0314e413320f9b3abe761259",
"0x5a14e72060c11313e38738009254a90968f58f51",
"0x5a7a51bfb49f190e5a6060a5bc6052ac14a3b59f",
"0x5d5b5dafecbf31bdb08bfd3edad4f2694372d0ef",
"0x5f48c2a71b2cc96e3f0ccae4e39318ff0dc375b2",
"0x67d40ee1a85bf4a4bb7ffae16de985e8427b6b45",
"0x6be0ae71e6c41f2f9d0d1a3b8d0f75e6f6a0b46e",
Expand All @@ -58,6 +59,7 @@
"0xa7e5d5a720f06526557c513402f2e6b5fa20b008",
"0xb338962b92cd818d6aef0a32a9ecd01212a71f33",
"0xb6f5ec1a0a9cd1526536d3f0426c429529471f40",
"0xc103b7dc095c904b92081eef0c1640081ec01c10",
"0xc2a3829f459b3edd87791c74cd45402ba0a20be3",
"0xc455f7fd3e0e12afd51fba5c106909934d8a0e4a",
"0xd0975b32cea532eadddfc9c60481976e39db3472",
Expand All @@ -67,6 +69,7 @@
"0xdb2720ebad55399117ddb4c4a4afd9a4ccada8fe",
"0xdcbeffbecce100cce9e4b153c4e15cb885643193",
"0xe1d865c3d669dcc8c57c8d023140cb204e672ee4",
"0xe1e4c5e5ed8f03ae61b581e2def126025f2b9401",
"0xe3d35f68383732649669aa990832e017340dbca5",
"0xe7aa314c77f4233c18c6cc84384a9247c0cf367b",
"0xe950dc316b836e4eefb8308bf32bf7c72a1358ff",
Expand Down
60 changes: 33 additions & 27 deletions pyinjective/orderhash.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,53 @@
from decimal import Decimal

import requests
from eip712.messages import EIP712Message, EIP712Type
from eip712.messages import EIP712Domain, EIP712Message
from eth_account.messages import _hash_eip191_message as hash_eip191_message
from eth_pydantic_types import abi
from hexbytes import HexBytes
from pydantic import BaseModel

from pyinjective.core.token import Token


class OrderInfo(EIP712Type):
SubaccountId: "string" # noqa: F821
FeeRecipient: "string" # noqa: F821
Price: "string" # noqa: F821
Quantity: "string" # noqa: F821
class OrderInfo(BaseModel):
SubaccountId: abi.string
FeeRecipient: abi.string
Price: abi.string
Quantity: abi.string


class SpotOrder(EIP712Message):
_name_ = "Injective Protocol"
_version_ = "2.0.0"
_chainId_ = 888
_verifyingContract_ = "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
_salt_ = HexBytes("0x0000000000000000000000000000000000000000000000000000000000000000")

MarketId: "string" # noqa: F821
eip712_domain = EIP712Domain(
name="Injective Protocol",
version="2.0.0",
chainId=888,
verifyingContract="0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
salt=HexBytes("0x0000000000000000000000000000000000000000000000000000000000000000"),
)
Comment on lines +21 to +27
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for chainId references
echo "=== Searching for chainId references ==="
rg -n "chainId" --type py -C 2

echo ""
echo "=== Searching for verifyingContract references ==="
rg -n "verifyingContract" --type py -C 2

echo ""
echo "=== Searching for EIP712Domain usage ==="
rg -n "EIP712Domain" --type py -C 3

echo ""
echo "=== Searching for network or environment configuration ==="
rg -n "MAINNET|TESTNET|DEVNET|network" --type py | head -30

echo ""
echo "=== Checking orderhash.py file context ==="
cat -n pyinjective/orderhash.py | head -60

Repository: InjectiveLabs/sdk-python

Length of output: 11373


🏁 Script executed:

#!/bin/bash
# Check the build_eip712_msg function and how it uses the network parameter
echo "=== Checking build_eip712_msg function ==="
sed -n '70,120p' pyinjective/orderhash.py

echo ""
echo "=== Check if there are any related issues or TODOs ==="
rg -n "TODO|FIXME|XXX|HACK" pyinjective/orderhash.py -C 2

echo ""
echo "=== Check for any test files related to orderhash ==="
fd -e py "orderhash" tests/

echo ""
echo "=== Check if chainId=888 appears in tests ==="
rg -n "888" --type py | grep -E "(test_|orderhash)" | head -20

Repository: InjectiveLabs/sdk-python

Length of output: 3024


🏁 Script executed:

#!/bin/bash
# Check the test_orderhash.py file
echo "=== Full test_orderhash.py file ==="
cat -n tests/test_orderhash.py

echo ""
echo "=== Check Network class to see what chain IDs are available ==="
rg -n "class Network" pyinjective/core/ -A 20 | head -80

echo ""
echo "=== Check if there's documentation about chainId=888 ==="
fd -e md -e txt -e rst . | xargs grep -l "888\|chainId" 2>/dev/null | head -10

Repository: InjectiveLabs/sdk-python

Length of output: 4246


🏁 Script executed:

#!/bin/bash
# Get the chain_id values used in Network class
echo "=== Check Network devnet chain_id ==="
rg -n "devnet\|testnet\|mainnet" pyinjective/core/network.py -A 5 | head -100

echo ""
echo "=== Look for static Network factory methods ==="
rg -n "def devnet|def testnet|def mainnet" pyinjective/core/network.py -A 10 | head -100

echo ""
echo "=== Check what chain_id value is used in Network initialization ==="
rg -n "chain_id.*=" pyinjective/core/network.py | head -20

Repository: InjectiveLabs/sdk-python

Length of output: 2033


🏁 Script executed:

#!/bin/bash
# Let's verify the numeric chain IDs and understand the pattern
echo "=== Summary of chain_ids ==="
grep -n "chain_id=" pyinjective/core/network.py | grep -E "(devnet|testnet|mainnet)"

echo ""
echo "=== Check if chainId in EIP712Domain should be numeric or string ==="
rg -n "chainId" --type py -B 2 -A 2

echo ""
echo "=== Verify that network parameter is passed but not used in orderhash ==="
sed -n '58,85p' pyinjective/orderhash.py

Repository: InjectiveLabs/sdk-python

Length of output: 5583


🏁 Script executed:

#!/bin/bash
# Extract numeric chain IDs from network definitions
echo "=== Extract numeric chain IDs from network string values ==="
grep "chain_id=" pyinjective/core/network.py | grep -E "injective-[0-9]" | sed 's/.*injective-//' | sed 's/".*//'

echo ""
echo "=== Verify the relationship between string chain_ids and numeric chainId ==="
echo "devnet: chain_id='injective-777' -> numeric chainId should be 777"
echo "testnet: chain_id='injective-888' -> numeric chainId should be 888"
echo "mainnet: chain_id='injective-1' -> numeric chainId should be 1"
echo ""
echo "Current hardcoded value in orderhash.py: chainId=888 (testnet only)"

echo ""
echo "=== Check if network parameter contains chain_id information ==="
grep -n "self.chain_id" pyinjective/core/network.py | head -5
</parameter>

Repository: InjectiveLabs/sdk-python

Length of output: 713


🏁 Script executed:

#!/bin/bash
# Confirm the issue: network parameter has chain_id but it's not used in orderhash
echo "=== Check if OrderHashManager stores network for later use ==="
sed -n '65,105p' pyinjective/orderhash.py

echo ""
echo "=== Confirm that network.chain_id is available but not used ==="
echo "Network object has chain_id attribute (line 132 in network.py)"
echo "But build_eip712_msg function doesn't accept or use network parameter"

grep -n "def build_eip712_msg" pyinjective/orderhash.py -A 15

Repository: InjectiveLabs/sdk-python

Length of output: 2487


Make EIP712 domain configuration network-aware instead of hardcoded.

The chainId=888 in the EIP712Domain is hardcoded to testnet, but the SDK supports multiple networks (devnet with chain_id="injective-777", testnet with chain_id="injective-888", mainnet with chain_id="injective-1"). The network parameter passed to OrderHashManager contains the correct chain ID but is never stored or used—it's only used to fetch endpoint URLs. This causes orders hashed on devnet or mainnet to have incorrect EIP712 domain values. Extract the numeric chain ID from the network parameter and pass it to the EIP712Domain construction.

🤖 Prompt for AI Agents
In pyinjective/orderhash.py around lines 21 to 27, the EIP712Domain is using a
hardcoded chainId=888; instead, store the incoming network parameter on the
OrderHashManager instance and derive the numeric chain ID from it (e.g., parse
digits from "injective-777"/"injective-888"/"injective-1" or use a
network.chain_id property if present) and pass that numeric value into
EIP712Domain.chainId so the domain matches devnet/testnet/mainnet.


MarketId: abi.string
OrderInfo: OrderInfo
Salt: "string" # noqa: F821
OrderType: "string" # noqa: F821
TriggerPrice: "string" # noqa: F821
Salt: abi.string
OrderType: abi.string
TriggerPrice: abi.string


class DerivativeOrder(EIP712Message):
_name_ = "Injective Protocol"
_version_ = "2.0.0"
_chainId_ = 888
_verifyingContract_ = "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
_salt_ = HexBytes("0x0000000000000000000000000000000000000000000000000000000000000000")

MarketId: "string" # noqa: F821
eip712_domain = EIP712Domain(
name="Injective Protocol",
version="2.0.0",
chainId=888,
verifyingContract="0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
salt=HexBytes("0x0000000000000000000000000000000000000000000000000000000000000000"),
)

MarketId: abi.string
OrderInfo: OrderInfo
OrderType: "string" # noqa: F821
Margin: "string" # noqa: F821
TriggerPrice: "string" # noqa: F821
Salt: "string" # noqa: F821
OrderType: abi.string
Margin: abi.string
TriggerPrice: abi.string
Salt: abi.string


# domain_separator = EIP712_domain.hash_struct()
Expand Down
Loading
Loading