Skip to content

Commit 79d4a0a

Browse files
authored
Merge pull request #402 from InjectiveLabs/release/chain_v1_17_0_support_to_master
Release/chain v1.17.0 support to master
2 parents fb9fcd0 + 162ad40 commit 79d4a0a

File tree

104 files changed

+8862
-3171
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+8862
-3171
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [1.12.0] - 2025-11-10
6+
### Changed
7+
- Updated all compiled protos for compatibility with Injective core v1.17.0 and Indexer v1.17.16
8+
- Included the OpenNotionalCap in derivative markets
9+
- Added support for market orders creation with the MsgBatchUpdateOrders message
10+
- Support for order failure events and conditional orders trigger failures in the chainstrem updates
11+
512
## [1.11.2] - 2025-09-24
613
### Added
714
- Added support in v2 Composer to create the new exchange module MsgCancelPostOnlyMode message

Makefile

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,14 @@ fix-generated-proto-imports:
1919
@find ./pyinjective/proto -type f -name "*.py" -exec sed -i "" -e "s/from google.api/from pyinjective.proto.google.api/g" {} \;
2020

2121
define clean_repos
22-
rm -Rf cosmos-sdk
23-
rm -Rf ibc-go
24-
rm -Rf cometbft
25-
rm -Rf wasmd
26-
rm -Rf injective-core
2722
rm -Rf injective-indexer
2823
endef
2924

3025
clean-all:
3126
$(call clean_repos)
3227

3328
clone-injective-indexer:
34-
git clone https://github.com/InjectiveLabs/injective-indexer.git -b v1.16.91 --depth 1 --single-branch
29+
git clone https://github.com/InjectiveLabs/injective-indexer.git -b v1.17.16 --depth 1 --single-branch
3530

3631
clone-all: clone-injective-indexer
3732

buf.gen.yaml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,21 @@ inputs:
1212
- module: buf.build/googleapis/googleapis
1313
- module: buf.build/cosmos/ics23
1414
- git_repo: https://github.com/InjectiveLabs/ibc-go
15-
tag: v8.7.0-evm-comet1-inj
15+
tag: v8.7.0-inj.3
1616
- git_repo: https://github.com/InjectiveLabs/wasmd
17-
tag: v0.53.3-evm-comet1-inj
17+
tag: v0.53.3-inj.2
1818
- git_repo: https://github.com/InjectiveLabs/cometbft
19-
tag: v1.0.1-inj.3
19+
tag: v1.0.1-inj.4
2020
- git_repo: https://github.com/InjectiveLabs/cosmos-sdk
21-
tag: v0.50.13-evm-comet1-inj.6
21+
tag: v0.50.14-inj
2222
# - git_repo: https://github.com/InjectiveLabs/wasmd
2323
# branch: v0.51.x-inj
2424
# subdir: proto
25+
- git_repo: https://github.com/InjectiveLabs/hyperlane-cosmos
26+
tag: v1.0.1-inj
27+
subdir: proto
2528
- git_repo: https://github.com/InjectiveLabs/injective-core
26-
tag: v1.16.4
29+
tag: v1.17.0
2730
subdir: proto
2831
# - git_repo: https://github.com/InjectiveLabs/injective-core
2932
# branch: master
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import asyncio
2+
from decimal import Decimal
3+
4+
from pyinjective.async_client_v2 import AsyncClient
5+
from pyinjective.core.network import Network
6+
7+
8+
def adjusted_margin(
9+
quantity: Decimal, margin: Decimal, is_long: bool, cumulative_funding_entry: Decimal, cumulative_funding: Decimal
10+
) -> Decimal:
11+
unrealized_funding_payment = (cumulative_funding - cumulative_funding_entry) * quantity * (-1 if is_long else 1)
12+
return margin + unrealized_funding_payment
13+
14+
15+
async def main() -> None:
16+
# select network: local, testnet, mainnet
17+
network = Network.mainnet()
18+
19+
# initialize grpc client
20+
client = AsyncClient(network)
21+
22+
positions_per_market = dict()
23+
24+
positions_dict = await client.fetch_chain_positions()
25+
liquidable_positions = []
26+
27+
for position in positions_dict["state"]:
28+
if position["marketId"] not in positions_per_market:
29+
positions_per_market[position["marketId"]] = []
30+
positions_per_market[position["marketId"]].append(position)
31+
32+
derivative_markets = await client.fetch_chain_derivative_markets(
33+
status="Active",
34+
market_ids=list(positions_per_market.keys()),
35+
)
36+
37+
for market in derivative_markets["markets"]:
38+
client_market = (await client.all_derivative_markets())[market["market"]["marketId"]]
39+
market_mark_price = client_market._from_extended_chain_format(Decimal(market["markPrice"]))
40+
for position in positions_per_market[client_market.id]:
41+
is_long = position["position"]["isLong"]
42+
quantity = client_market._from_extended_chain_format(Decimal(position["position"]["quantity"]))
43+
entry_price = client_market._from_extended_chain_format(Decimal(position["position"]["entryPrice"]))
44+
margin = client_market._from_extended_chain_format(Decimal(position["position"]["margin"]))
45+
cumulative_funding_entry = client_market._from_extended_chain_format(
46+
Decimal(position["position"]["cumulativeFundingEntry"])
47+
)
48+
market_cumulative_funding = client_market._from_extended_chain_format(
49+
Decimal(market["perpetualInfo"]["fundingInfo"]["cumulativeFunding"])
50+
)
51+
52+
adj_margin = adjusted_margin(quantity, margin, is_long, cumulative_funding_entry, market_cumulative_funding)
53+
adjusted_unit_margin = (adj_margin / quantity) * (-1 if is_long else 1)
54+
maintenance_margin_ratio = client_market.maintenance_margin_ratio * (-1 if is_long else 1)
55+
56+
liquidation_price = (entry_price + adjusted_unit_margin) / (Decimal(1) + maintenance_margin_ratio)
57+
58+
should_be_liquidated = (is_long and market_mark_price <= liquidation_price) or (
59+
not is_long and market_mark_price >= liquidation_price
60+
)
61+
62+
if should_be_liquidated:
63+
position_side = "Long" if is_long else "Short"
64+
print(
65+
f"{position_side} position for market {client_market.id} and subaccount "
66+
f"{position['subaccountId']} should be liquidated (liquidation price: "
67+
f"{liquidation_price.normalize()} / mark price: {market_mark_price.normalize()})"
68+
)
69+
liquidable_positions.append(position)
70+
71+
# print(f"\n\n\n")
72+
# print(json.dumps(liquidable_positions, indent=4))
73+
74+
75+
if __name__ == "__main__":
76+
asyncio.get_event_loop().run_until_complete(main())

examples/chain_client/7_ChainStream.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ async def main() -> None:
5050
subaccount_ids=[subaccount_id], market_ids=[inj_usdt_perp_market]
5151
)
5252
oracle_price_filter = composer.chain_stream_oracle_price_filter(symbols=["INJ", "USDT"])
53+
order_failures_filter = composer.chain_stream_order_failures_filter(
54+
accounts=["inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"]
55+
)
56+
conditional_order_trigger_failures_filter = composer.chain_stream_conditional_order_trigger_failures_filter(
57+
subaccount_ids=[subaccount_id], market_ids=[inj_usdt_perp_market]
58+
)
5359

5460
task = asyncio.get_event_loop().create_task(
5561
client.listen_chain_stream_updates(
@@ -66,6 +72,8 @@ async def main() -> None:
6672
derivative_orderbooks_filter=derivative_orderbooks_filter,
6773
positions_filter=positions_filter,
6874
oracle_price_filter=oracle_price_filter,
75+
order_failures_filter=order_failures_filter,
76+
conditional_order_trigger_failures_filter=conditional_order_trigger_failures_filter,
6977
)
7078
)
7179

examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ async def main() -> None:
5757
min_price_tick_size=Decimal("0.01"),
5858
min_quantity_tick_size=Decimal("0.01"),
5959
min_notional=Decimal("1"),
60+
open_notional_cap=composer.uncapped_open_notional_cap(),
6061
)
6162

6263
# broadcast the transaction

examples/chain_client/exchange/25_MsgUpdateDerivativeMarket.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ async def main() -> None:
5252
new_initial_margin_ratio=Decimal("0.40"),
5353
new_maintenance_margin_ratio=Decimal("0.085"),
5454
new_reduce_margin_ratio=Decimal("3.5"),
55+
new_open_notional_cap=composer.uncapped_open_notional_cap(),
5556
)
5657

5758
# broadcast the transaction
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import asyncio
2+
import json
3+
import os
4+
5+
import dotenv
6+
7+
from pyinjective.async_client_v2 import AsyncClient
8+
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
9+
from pyinjective.core.network import Network
10+
from pyinjective.wallet import PrivateKey
11+
12+
13+
async def main() -> None:
14+
dotenv.load_dotenv()
15+
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
16+
17+
# select network: local, testnet, mainnet
18+
network = Network.testnet()
19+
20+
# initialize grpc client
21+
client = AsyncClient(network)
22+
await client.initialize_tokens_from_chain_denoms()
23+
composer = await client.composer()
24+
25+
gas_price = await client.current_chain_gas_price()
26+
# adjust gas price to make it valid even if it changes between the time it is requested and the TX is broadcasted
27+
gas_price = int(gas_price * 1.1)
28+
29+
message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
30+
network=network,
31+
private_key=configured_private_key,
32+
gas_price=gas_price,
33+
client=client,
34+
composer=composer,
35+
)
36+
37+
# load account
38+
priv_key = PrivateKey.from_hex(configured_private_key)
39+
pub_key = priv_key.to_public_key()
40+
address = pub_key.to_address()
41+
await client.fetch_account(address.to_acc_bech32())
42+
43+
offsetting_subaccount_ids = {
44+
"0xbdaedec95d563fb05240d6e01821008454c24c36000000000000000000000000",
45+
"0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000",
46+
}
47+
48+
# prepare tx msg
49+
message = composer.msg_offset_position(
50+
sender=address.to_acc_bech32(),
51+
subaccount_id=address.get_subaccount_id(index=0),
52+
market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
53+
offsetting_subaccount_ids=offsetting_subaccount_ids,
54+
)
55+
56+
# broadcast the transaction
57+
result = await message_broadcaster.broadcast([message])
58+
print("---Transaction Response---")
59+
print(json.dumps(result, indent=2))
60+
61+
gas_price = await client.current_chain_gas_price()
62+
# adjust gas price to make it valid even if it changes between the time it is requested and the TX is broadcasted
63+
gas_price = int(gas_price * 1.1)
64+
message_broadcaster.update_gas_price(gas_price=gas_price)
65+
66+
67+
if __name__ == "__main__":
68+
asyncio.get_event_loop().run_until_complete(main())

examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ async def main() -> None:
5858
min_price_tick_size=Decimal("0.001"),
5959
min_quantity_tick_size=Decimal("0.01"),
6060
min_notional=Decimal("1"),
61+
open_notional_cap=composer.uncapped_open_notional_cap(),
6162
)
6263

6364
# broadcast the transaction

examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ async def main() -> None:
5858
min_price_tick_size=Decimal("0.001"),
5959
min_quantity_tick_size=Decimal("0.01"),
6060
min_notional=Decimal("1"),
61+
open_notional_cap=composer.uncapped_open_notional_cap(),
6162
)
6263

6364
# broadcast the transaction

0 commit comments

Comments
 (0)