Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/add exchange messages from v1.13 #341

Merged
merged 9 commits into from
Aug 6, 2024
2 changes: 1 addition & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ jobs:
poetry run pytest --cov --cov-report=xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
env_vars: OS,PYTHON
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

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

## [1.6.1] - 2024-08-07
### Added
- Added support for the following messages in the chain "exchange" module:
- MsgDecreasePositionMargin
- MsgUpdateSpotMarket
- MsgUpdateDerivativeMarket
- MsgAuthorizeStakeGrants
- MsgActivateStakeGrant

## [1.6.0] - 2024-07-30
### Added
- Support for all queries in the chain "tendermint" module
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,14 @@ async def main() -> None:
fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"

# set custom denom to bypass ini file load (optional)
denom = Denom(description="desc", base=0, quote=6, min_price_tick_size=1000, min_quantity_tick_size=0.0001)
denom = Denom(
description="desc",
base=0,
quote=6,
min_price_tick_size=1000,
min_quantity_tick_size=0.0001,
min_notional=0,
)

# prepare tx msg
msg = composer.msg_create_binary_options_limit_order(
Expand Down
56 changes: 56 additions & 0 deletions examples/chain_client/exchange/23_MsgDecreasePositionMargin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
Comment on lines +14 to +15
Copy link
Contributor

Choose a reason for hiding this comment

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

Handle missing environment variable.

Add error handling for the case when INJECTIVE_PRIVATE_KEY is not set.

dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
if configured_private_key is None:
    raise EnvironmentError("INJECTIVE_PRIVATE_KEY is not set in the environment.")
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
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
if configured_private_key is None:
raise EnvironmentError("INJECTIVE_PRIVATE_KEY is not set in the environment.")


# select network: local, testnet, mainnet
network = Network.testnet()

# initialize grpc client
client = AsyncClient(network)
composer = await client.composer()
await client.sync_timeout_height()

message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
network=network,
private_key=configured_private_key,
)
Comment on lines +25 to +28
Copy link
Contributor

Choose a reason for hiding this comment

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

Handle potential errors in transaction broadcasting.

Add error handling for the transaction broadcasting process to ensure robustness.

try:
    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=configured_private_key,
    )
except Exception as e:
    print(f"Error initializing message broadcaster: {e}")
    return
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
message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
network=network,
private_key=configured_private_key,
)
try:
message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
network=network,
private_key=configured_private_key,
)
except Exception as e:
print(f"Error initializing message broadcaster: {e}")
return


# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())
subaccount_id = address.get_subaccount_id(index=0)

# prepare trade info
market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"

# prepare tx msg
msg = composer.msg_decrease_position_margin(
sender=address.to_acc_bech32(),
market_id=market_id,
source_subaccount_id=subaccount_id,
destination_subaccount_id=subaccount_id,
amount=Decimal(2),
)

# broadcast the transaction
result = await message_broadcaster.broadcast([msg])
print("---Transaction Response---")
print(result)
Comment on lines +50 to +52
Copy link
Contributor

Choose a reason for hiding this comment

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

Handle potential errors in transaction response.

Add error handling for the transaction response to ensure robustness.

try:
    result = await message_broadcaster.broadcast([msg])
    print("---Transaction Response---")
    print(result)
except Exception as e:
    print(f"Error broadcasting transaction: {e}")
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
result = await message_broadcaster.broadcast([msg])
print("---Transaction Response---")
print(result)
try:
result = await message_broadcaster.broadcast([msg])
print("---Transaction Response---")
print(result)
except Exception as e:
print(f"Error broadcasting transaction: {e}")



if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
54 changes: 54 additions & 0 deletions examples/chain_client/exchange/24_MsgUpdateSpotMarket.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

# select network: local, testnet, mainnet
network = Network.testnet()

# initialize grpc client
client = AsyncClient(network)
await client.initialize_tokens_from_chain_denoms()
composer = await client.composer()
await client.sync_timeout_height()

message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
network=network,
private_key=configured_private_key,
)

# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())

# prepare tx msg
message = composer.msg_update_spot_market(
admin=address.to_acc_bech32(),
market_id="0x215970bfdea5c94d8e964a759d3ce6eae1d113900129cc8428267db5ccdb3d1a",
new_ticker="INJ/USDC 2",
new_min_price_tick_size=Decimal("0.01"),
new_min_quantity_tick_size=Decimal("0.01"),
new_min_notional=Decimal("2"),
)

# broadcast the transaction
result = await message_broadcaster.broadcast([message])
print("---Transaction Response---")
print(result)


if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
56 changes: 56 additions & 0 deletions examples/chain_client/exchange/25_MsgUpdateDerivativeMarket.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
Comment on lines +14 to +15
Copy link
Contributor

Choose a reason for hiding this comment

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

Handle missing environment variable.

Add error handling for the case when INJECTIVE_PRIVATE_KEY is not set.

dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
if configured_private_key is None:
    raise EnvironmentError("INJECTIVE_PRIVATE_KEY is not set in the environment.")
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
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")
if configured_private_key is None:
raise EnvironmentError("INJECTIVE_PRIVATE_KEY is not set in the environment.")


# select network: local, testnet, mainnet
network = Network.testnet()

# initialize grpc client
client = AsyncClient(network)
await client.initialize_tokens_from_chain_denoms()
composer = await client.composer()
await client.sync_timeout_height()

message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
network=network,
private_key=configured_private_key,
)
Comment on lines +26 to +29
Copy link
Contributor

Choose a reason for hiding this comment

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

Handle potential errors in transaction broadcasting.

Add error handling for the transaction broadcasting process to ensure robustness.

try:
    message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
        network=network,
        private_key=configured_private_key,
    )
except Exception as e:
    print(f"Error initializing message broadcaster: {e}")
    return
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
message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
network=network,
private_key=configured_private_key,
)
try:
message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
network=network,
private_key=configured_private_key,
)
except Exception as e:
print(f"Error initializing message broadcaster: {e}")
return


# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())

# prepare tx msg
message = composer.msg_update_derivative_market(
admin=address.to_acc_bech32(),
market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6",
new_ticker="INJ/USDT PERP 2",
new_min_price_tick_size=Decimal("1"),
new_min_quantity_tick_size=Decimal("1"),
new_min_notional=Decimal("2"),
new_initial_margin_ratio=Decimal("0.40"),
new_maintenance_margin_ratio=Decimal("0.085"),
)

# broadcast the transaction
result = await message_broadcaster.broadcast([message])
print("---Transaction Response---")
print(result)
Comment on lines +50 to +52
Copy link
Contributor

Choose a reason for hiding this comment

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

Handle potential errors in transaction response.

Add error handling for the transaction response to ensure robustness.

try:
    result = await message_broadcaster.broadcast([message])
    print("---Transaction Response---")
    print(result)
except Exception as e:
    print(f"Error broadcasting transaction: {e}")
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
result = await message_broadcaster.broadcast([message])
print("---Transaction Response---")
print(result)
try:
result = await message_broadcaster.broadcast([message])
print("---Transaction Response---")
print(result)
except Exception as e:
print(f"Error broadcasting transaction: {e}")



if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
51 changes: 51 additions & 0 deletions examples/chain_client/exchange/26_MsgAuthorizeStakeGrants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import asyncio
import os
from decimal import Decimal

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

# select network: local, testnet, mainnet
network = Network.testnet()

# initialize grpc client
client = AsyncClient(network)
await client.initialize_tokens_from_chain_denoms()
composer = await client.composer()
await client.sync_timeout_height()

message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
network=network,
private_key=configured_private_key,
)

# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())

# prepare tx msg
grant_authorization = composer.create_grant_authorization(
grantee="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r",
amount=Decimal("1"),
)
message = composer.msg_authorize_stake_grants(sender=address.to_acc_bech32(), grants=[grant_authorization])

# broadcast the transaction
result = await message_broadcaster.broadcast([message])
print("---Transaction Response---")
print(result)


if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
48 changes: 48 additions & 0 deletions examples/chain_client/exchange/27_MsgActivateStakeGrant.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import asyncio
import os

import dotenv

from pyinjective.async_client import AsyncClient
from pyinjective.core.broadcaster import MsgBroadcasterWithPk
from pyinjective.core.network import Network
from pyinjective.wallet import PrivateKey


async def main() -> None:
dotenv.load_dotenv()
configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY")

# select network: local, testnet, mainnet
network = Network.testnet()

# initialize grpc client
client = AsyncClient(network)
await client.initialize_tokens_from_chain_denoms()
composer = await client.composer()
await client.sync_timeout_height()

message_broadcaster = MsgBroadcasterWithPk.new_using_simulation(
network=network,
private_key=configured_private_key,
)

# load account
priv_key = PrivateKey.from_hex(configured_private_key)
pub_key = priv_key.to_public_key()
address = pub_key.to_address()
await client.fetch_account(address.to_acc_bech32())

# prepare tx msg
message = composer.msg_activate_stake_grant(
sender=address.to_acc_bech32(), granter="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"
)

# broadcast the transaction
result = await message_broadcaster.broadcast([message])
print("---Transaction Response---")
print(result)


if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
Comment on lines +47 to +48
Copy link
Contributor

Choose a reason for hiding this comment

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

Use asyncio.run instead of get_event_loop.

Using asyncio.run is a more modern and preferred way to run the main function.

- asyncio.get_event_loop().run_until_complete(main())
+ asyncio.run(main())
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
if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
if __name__ == "__main__":
asyncio.run(main())

3 changes: 3 additions & 0 deletions pyinjective/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3324,6 +3324,7 @@ async def _initialize_tokens_and_markets(self):
service_provider_fee=Decimal(market_info["serviceProviderFee"]),
min_price_tick_size=Decimal(market_info["minPriceTickSize"]),
min_quantity_tick_size=Decimal(market_info["minQuantityTickSize"]),
min_notional=Decimal(market_info["minNotional"]),
)

spot_markets[market.id] = market
Expand Down Expand Up @@ -3359,6 +3360,7 @@ async def _initialize_tokens_and_markets(self):
service_provider_fee=Decimal(market_info["serviceProviderFee"]),
min_price_tick_size=Decimal(market_info["minPriceTickSize"]),
min_quantity_tick_size=Decimal(market_info["minQuantityTickSize"]),
min_notional=Decimal(market_info["minNotional"]),
)

derivative_markets[market.id] = market
Expand All @@ -3383,6 +3385,7 @@ async def _initialize_tokens_and_markets(self):
service_provider_fee=Decimal(market_info["serviceProviderFee"]),
min_price_tick_size=Decimal(market_info["minPriceTickSize"]),
min_quantity_tick_size=Decimal(market_info["minQuantityTickSize"]),
min_notional=Decimal(market_info["minNotional"]),
settlement_price=None
if market_info["settlementPrice"] == ""
else Decimal(market_info["settlementPrice"]),
Expand Down
Loading
Loading