diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 00000000..930db111 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,8 @@ +reviews: + auto_review: + base_branches: + - "master" + - "dev" + - "feat/.*" +chat: + auto_reply: true diff --git a/CHANGELOG.md b/CHANGELOG.md index d6f16f42..876c5845 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## [1.4.0] - 2024-03-11 +### Added +- Added support for all queries and messages in the chain 'distribution' module +- Added support for all queries and messages in the chain 'exchange' module +- Use of python-dotenv in all example scripts to load private keys from a .env file + ## [1.3.1] - 2024-02-29 ### Changed - Updated cookie assistant logic to support the Indexer exchange server not using cookies and the chain server using them diff --git a/examples/SendToInjective.py b/examples/SendToInjective.py index b03988b4..23469642 100644 --- a/examples/SendToInjective.py +++ b/examples/SendToInjective.py @@ -1,16 +1,21 @@ import asyncio import json +import os + +import dotenv from pyinjective.core.network import Network from pyinjective.sendtocosmos import Peggo async def main() -> None: + dotenv.load_dotenv() + private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: testnet, mainnet network = Network.testnet() peggo_composer = Peggo(network=network.string()) - private_key = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" ethereum_endpoint = "https://eth-goerli.g.alchemy.com/v2/q-7JVv4mTfsNh1y_djKkKn3maRBGILLL" maxFeePerGas_Gwei = 4 diff --git a/examples/chain_client/0_LocalOrderHash.py b/examples/chain_client/1_LocalOrderHash.py similarity index 73% rename from examples/chain_client/0_LocalOrderHash.py rename to examples/chain_client/1_LocalOrderHash.py index c81c3e2e..fbec8988 100644 --- a/examples/chain_client/0_LocalOrderHash.py +++ b/examples/chain_client/1_LocalOrderHash.py @@ -1,5 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal + +import dotenv from pyinjective.async_client import AsyncClient from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE @@ -10,6 +14,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +26,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -34,57 +41,59 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" spot_orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.524, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("0.524"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=27.92, - quantity=0.01, - is_buy=False, - is_po=False, + price=Decimal("27.92"), + quantity=Decimal("0.01"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] derivative_orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=10500, - quantity=0.01, - leverage=1.5, - is_buy=True, - is_po=False, + price=Decimal(10500), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(10500), leverage=Decimal(2), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=65111, - quantity=0.01, - leverage=2, - is_buy=False, - is_reduce_only=False, + price=Decimal(65111), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(65111), leverage=Decimal(2), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ), ] # prepare tx msg - spot_msg = composer.MsgBatchCreateSpotLimitOrders(sender=address.to_acc_bech32(), orders=spot_orders) + spot_msg = composer.msg_batch_create_spot_limit_orders(sender=address.to_acc_bech32(), orders=spot_orders) - deriv_msg = composer.MsgBatchCreateDerivativeLimitOrders(sender=address.to_acc_bech32(), orders=derivative_orders) + deriv_msg = composer.msg_batch_create_derivative_limit_orders( + sender=address.to_acc_bech32(), orders=derivative_orders + ) # compute order hashes order_hashes = order_hash_manager.compute_order_hashes( @@ -107,7 +116,7 @@ async def main() -> None: gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) @@ -144,7 +153,7 @@ async def main() -> None: gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) @@ -161,57 +170,59 @@ async def main() -> None: print("gas fee: {} INJ".format(gas_fee)) spot_orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=1.524, - quantity=0.01, - is_buy=True, - is_po=True, + price=Decimal("1.524"), + quantity=Decimal("0.01"), + order_type="BUY_PO", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=27.92, - quantity=0.01, - is_buy=False, - is_po=False, + price=Decimal("27.92"), + quantity=Decimal("0.01"), + order_type="SELL_PO", cid=str(uuid.uuid4()), ), ] derivative_orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=25111, - quantity=0.01, - leverage=1.5, - is_buy=True, - is_po=False, + price=Decimal(25111), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(25111), leverage=Decimal("1.5"), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=65111, - quantity=0.01, - leverage=2, - is_buy=False, - is_reduce_only=False, + price=Decimal(65111), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(25111), leverage=Decimal(2), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ), ] # prepare tx msg - spot_msg = composer.MsgBatchCreateSpotLimitOrders(sender=address.to_acc_bech32(), orders=spot_orders) + spot_msg = composer.msg_batch_create_spot_limit_orders(sender=address.to_acc_bech32(), orders=spot_orders) - deriv_msg = composer.MsgBatchCreateDerivativeLimitOrders(sender=address.to_acc_bech32(), orders=derivative_orders) + deriv_msg = composer.msg_batch_create_derivative_limit_orders( + sender=address.to_acc_bech32(), orders=derivative_orders + ) # compute order hashes order_hashes = order_hash_manager.compute_order_hashes( @@ -234,7 +245,7 @@ async def main() -> None: gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/26_MsgWithdrawDelegatorReward.py b/examples/chain_client/26_MsgWithdrawDelegatorReward.py deleted file mode 100644 index 77210421..00000000 --- a/examples/chain_client/26_MsgWithdrawDelegatorReward.py +++ /dev/null @@ -1,76 +0,0 @@ -import asyncio - -from grpc import RpcError - -from pyinjective.async_client import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE -from pyinjective.core.network import Network -from pyinjective.transaction import Transaction -from pyinjective.wallet import PrivateKey - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - composer = await client.composer() - await client.sync_timeout_height() - - # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - # prepare tx msg - validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" - - msg = composer.MsgWithdrawDelegatorReward( - delegator_address=address.to_acc_bech32(), validator_address=validator_address - ) - - # build sim tx - tx = ( - Transaction() - .with_messages(msg) - .with_sequence(client.get_sequence()) - .with_account_num(client.get_number()) - .with_chain_id(network.chain_id) - ) - sim_sign_doc = tx.get_sign_doc(pub_key) - sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) - sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key) - - # simulate tx - try: - sim_res = await client.simulate(sim_tx_raw_bytes) - except RpcError as ex: - print(ex) - return - - # build tx - gas_price = GAS_PRICE - gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation - gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") - fee = [ - composer.Coin( - amount=gas_price * gas_limit, - denom=network.fee_denom, - ) - ] - tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height) - sign_doc = tx.get_sign_doc(pub_key) - sig = priv_key.sign(sign_doc.SerializeToString()) - tx_raw_bytes = tx.get_tx_data(sig, pub_key) - - # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode - res = await client.broadcast_tx_sync_mode(tx_raw_bytes) - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/38_StreamEventOrderFail.py b/examples/chain_client/2_StreamEventOrderFail.py similarity index 100% rename from examples/chain_client/38_StreamEventOrderFail.py rename to examples/chain_client/2_StreamEventOrderFail.py diff --git a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py deleted file mode 100644 index e0881db5..00000000 --- a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py +++ /dev/null @@ -1,93 +0,0 @@ -import asyncio - -from grpc import RpcError - -from pyinjective.async_client import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE -from pyinjective.core.network import Network -from pyinjective.transaction import Transaction -from pyinjective.wallet import PrivateKey - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - composer = await client.composer() - await client.sync_timeout_height() - - # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - # prepare tx msg - msg = composer.MsgInstantBinaryOptionsMarketLaunch( - sender=address.to_acc_bech32(), - admin=address.to_acc_bech32(), - ticker="UFC-KHABIB-TKO-05/30/2023", - oracle_symbol="UFC-KHABIB-TKO-05/30/2023", - oracle_provider="UFC", - oracle_type="Provider", - quote_denom="peggy0xdAC17F958D2ee523a2206206994597C13D831ec7", - quote_decimals=6, - oracle_scale_factor=6, - maker_fee_rate=0.0005, # 0.05% - taker_fee_rate=0.0010, # 0.10% - expiration_timestamp=1680730982, - settlement_timestamp=1690730982, - min_price_tick_size=0.01, - min_quantity_tick_size=0.01, - ) - - # build sim tx - tx = ( - Transaction() - .with_messages(msg) - .with_sequence(client.get_sequence()) - .with_account_num(client.get_number()) - .with_chain_id(network.chain_id) - ) - sim_sign_doc = tx.get_sign_doc(pub_key) - sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) - sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key) - - # simulate tx - try: - sim_res = await client.simulate(sim_tx_raw_bytes) - except RpcError as ex: - print(ex) - return - - sim_res_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) - - # build tx - gas_price = GAS_PRICE - gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation - gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") - fee = [ - composer.Coin( - amount=gas_price * gas_limit, - denom=network.fee_denom, - ) - ] - tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height) - sign_doc = tx.get_sign_doc(pub_key) - sig = priv_key.sign(sign_doc.SerializeToString()) - tx_raw_bytes = tx.get_tx_data(sig, pub_key) - - # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode - res = await client.broadcast_tx_sync_mode(tx_raw_bytes) - print("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/44_MessageBroadcaster.py b/examples/chain_client/3_MessageBroadcaster.py similarity index 79% rename from examples/chain_client/44_MessageBroadcaster.py rename to examples/chain_client/3_MessageBroadcaster.py index a9bb1f68..6bd67033 100644 --- a/examples/chain_client/44_MessageBroadcaster.py +++ b/examples/chain_client/3_MessageBroadcaster.py @@ -1,5 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -8,10 +12,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, @@ -29,24 +35,22 @@ async def main() -> None: spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" spot_orders_to_create = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=3, - quantity=55, - is_buy=True, - is_po=False, - cid=str(uuid.uuid4()), + price=Decimal("3"), + quantity=Decimal("55"), + order_type="BUY", + cid=(str(uuid.uuid4())), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=300, - quantity=55, - is_buy=False, - is_po=False, + price=Decimal("300"), + quantity=Decimal("55"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] diff --git a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py b/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py deleted file mode 100644 index b46ca371..00000000 --- a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py +++ /dev/null @@ -1,81 +0,0 @@ -import asyncio - -from grpc import RpcError - -from pyinjective.async_client import AsyncClient -from pyinjective.composer import Composer as ProtoMsgComposer -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE -from pyinjective.core.network import Network -from pyinjective.transaction import Transaction -from pyinjective.wallet import PrivateKey - - -async def main() -> None: - """For a validator to withdraw his rewards & commissions simultaneously""" - # select network: local, testnet, mainnet - network = Network.testnet() - composer = ProtoMsgComposer(network=network.string()) - - # initialize grpc client - client = AsyncClient(network, insecure=False) - await client.sync_timeout_height() - - # load account - # private key is that from the validator's wallet - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - # prepare tx msg - validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" - - msg0 = composer.MsgWithdrawDelegatorReward( - delegator_address=address.to_acc_bech32(), validator_address=validator_address - ) - - msg1 = composer.MsgWithdrawValidatorCommission(validator_address=validator_address) - - # build sim tx - tx = ( - Transaction() - .with_messages(msg0, msg1) - .with_sequence(client.get_sequence()) - .with_account_num(client.get_number()) - .with_chain_id(network.chain_id) - ) - sim_sign_doc = tx.get_sign_doc(pub_key) - sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) - sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key) - - # simulate tx - try: - sim_res = await client.simulate(sim_tx_raw_bytes) - except RpcError as ex: - print(ex) - return - - # build tx - gas_price = GAS_PRICE - gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation - gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") - fee = [ - composer.Coin( - amount=gas_price * gas_limit, - denom=network.fee_denom, - ) - ] - tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height) - sign_doc = tx.get_sign_doc(pub_key) - sig = priv_key.sign(sign_doc.SerializeToString()) - tx_raw_bytes = tx.get_tx_data(sig, pub_key) - - # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode - res = await client.broadcast_tx_sync_mode(tx_raw_bytes) - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py b/examples/chain_client/4_MessageBroadcasterWithGranteeAccount.py similarity index 81% rename from examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py rename to examples/chain_client/4_MessageBroadcasterWithGranteeAccount.py index 59c04af2..4e08397b 100644 --- a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py +++ b/examples/chain_client/4_MessageBroadcasterWithGranteeAccount.py @@ -1,5 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal + +import dotenv from pyinjective.async_client import AsyncClient from pyinjective.composer import Composer as ProtoMsgComposer @@ -9,6 +13,10 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") + granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) @@ -18,7 +26,6 @@ async def main() -> None: await client.sync_timeout_height() # load account - private_key_in_hexa = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() @@ -30,19 +37,18 @@ async def main() -> None: # prepare tx msg market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) - msg = composer.MsgCreateSpotLimitOrder( - sender=granter_inj_address, + msg = composer.msg_create_spot_limit_order( market_id=market_id, + sender=granter_inj_address, subaccount_id=granter_subaccount_id, fee_recipient=address.to_acc_bech32(), - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py b/examples/chain_client/5_MessageBroadcasterWithoutSimulation.py similarity index 81% rename from examples/chain_client/46_MessageBroadcasterWithoutSimulation.py rename to examples/chain_client/5_MessageBroadcasterWithoutSimulation.py index 908a4579..54a79bf8 100644 --- a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py +++ b/examples/chain_client/5_MessageBroadcasterWithoutSimulation.py @@ -1,5 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -8,10 +12,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( network=network, @@ -29,24 +35,22 @@ async def main() -> None: spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" spot_orders_to_create = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=3, - quantity=55, - is_buy=True, - is_po=False, + price=Decimal("3"), + quantity=Decimal("55"), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=300, - quantity=55, - is_buy=False, - is_po=False, + price=Decimal("300"), + quantity=Decimal("55"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] diff --git a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py b/examples/chain_client/6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py similarity index 81% rename from examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py rename to examples/chain_client/6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py index ebae28ab..4b7fbd2e 100644 --- a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py +++ b/examples/chain_client/6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py @@ -1,5 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal + +import dotenv from pyinjective.async_client import AsyncClient from pyinjective.composer import Composer as ProtoMsgComposer @@ -9,6 +13,10 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") + granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) @@ -18,7 +26,6 @@ async def main() -> None: await client.sync_timeout_height() # load account - private_key_in_hexa = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() @@ -30,19 +37,17 @@ async def main() -> None: # prepare tx msg market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) - msg = composer.MsgCreateSpotLimitOrder( - sender=granter_inj_address, + msg = composer.msg_create_spot_limit_order( market_id=market_id, + sender=granter_inj_address, subaccount_id=granter_subaccount_id, fee_recipient=address.to_acc_bech32(), - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/49_ChainStream.py b/examples/chain_client/7_ChainStream.py similarity index 100% rename from examples/chain_client/49_ChainStream.py rename to examples/chain_client/7_ChainStream.py diff --git a/examples/chain_client/18_MsgBid.py b/examples/chain_client/auction/1_MsgBid.py similarity index 91% rename from examples/chain_client/18_MsgBid.py rename to examples/chain_client/auction/1_MsgBid.py index 9e51e075..1efaa3e3 100644 --- a/examples/chain_client/18_MsgBid.py +++ b/examples/chain_client/auction/1_MsgBid.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -51,7 +56,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/39_Account.py b/examples/chain_client/auth/query/1_Account.py similarity index 100% rename from examples/chain_client/39_Account.py rename to examples/chain_client/auth/query/1_Account.py diff --git a/examples/chain_client/19_MsgGrant.py b/examples/chain_client/authz/1_MsgGrant.py similarity index 88% rename from examples/chain_client/19_MsgGrant.py rename to examples/chain_client/authz/1_MsgGrant.py index 0d00d489..111a050c 100644 --- a/examples/chain_client/19_MsgGrant.py +++ b/examples/chain_client/authz/1_MsgGrant.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -30,8 +36,8 @@ async def main() -> None: # GENERIC AUTHZ msg = composer.MsgGrantGeneric( - granter="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", - grantee="inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku", + granter=address.to_acc_bech32(), + grantee=grantee_public_address, msg_type="/injective.exchange.v1beta1.MsgCreateSpotLimitOrder", expire_in=31536000, # 1 year ) @@ -70,7 +76,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/20_MsgExec.py b/examples/chain_client/authz/2_MsgExec.py similarity index 85% rename from examples/chain_client/20_MsgExec.py rename to examples/chain_client/authz/2_MsgExec.py index a2876d6a..8d9891a5 100644 --- a/examples/chain_client/20_MsgExec.py +++ b/examples/chain_client/authz/2_MsgExec.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +14,10 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") + granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,26 +27,25 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e") + 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 market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - grantee = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku" - granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + grantee = address.to_acc_bech32() + granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) - msg0 = composer.MsgCreateSpotLimitOrder( + msg0 = composer.msg_create_spot_limit_order( sender=granter_inj_address, market_id=market_id, subaccount_id=granter_subaccount_id, fee_recipient=grantee, - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) @@ -77,7 +83,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/21_MsgRevoke.py b/examples/chain_client/authz/3_MsgRevoke.py similarity index 86% rename from examples/chain_client/21_MsgRevoke.py rename to examples/chain_client/authz/3_MsgRevoke.py index 2cafab7f..91bb192d 100644 --- a/examples/chain_client/21_MsgRevoke.py +++ b/examples/chain_client/authz/3_MsgRevoke.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,15 +25,15 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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 msg = composer.MsgRevoke( - granter="inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku", - grantee="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + granter=address.to_acc_bech32(), + grantee=grantee_public_address, msg_type="/injective.exchange.v1beta1.MsgCreateSpotLimitOrder", ) @@ -55,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/27_Grants.py b/examples/chain_client/authz/query/1_Grants.py similarity index 74% rename from examples/chain_client/27_Grants.py rename to examples/chain_client/authz/query/1_Grants.py index 331980af..9ab27f22 100644 --- a/examples/chain_client/27_Grants.py +++ b/examples/chain_client/authz/query/1_Grants.py @@ -1,14 +1,19 @@ import asyncio +import os + +import dotenv from pyinjective.async_client import AsyncClient from pyinjective.core.network import Network async def main() -> None: + dotenv.load_dotenv() + granter = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + grantee = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + network = Network.testnet() client = AsyncClient(network) - granter = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku" - grantee = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" msg_type_url = "/injective.exchange.v1beta1.MsgCreateDerivativeLimitOrder" authorizations = await client.fetch_grants(granter=granter, grantee=grantee, msg_type_url=msg_type_url) print(authorizations) diff --git a/examples/chain_client/1_MsgSend.py b/examples/chain_client/bank/1_MsgSend.py similarity index 92% rename from examples/chain_client/1_MsgSend.py rename to examples/chain_client/bank/1_MsgSend.py index 9b9651f7..1d926898 100644 --- a/examples/chain_client/1_MsgSend.py +++ b/examples/chain_client/bank/1_MsgSend.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -56,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/57_SendEnabled.py b/examples/chain_client/bank/query/10_SendEnabled.py similarity index 100% rename from examples/chain_client/57_SendEnabled.py rename to examples/chain_client/bank/query/10_SendEnabled.py diff --git a/examples/chain_client/29_BankBalance.py b/examples/chain_client/bank/query/1_BankBalance.py similarity index 100% rename from examples/chain_client/29_BankBalance.py rename to examples/chain_client/bank/query/1_BankBalance.py diff --git a/examples/chain_client/28_BankBalances.py b/examples/chain_client/bank/query/2_BankBalances.py similarity index 100% rename from examples/chain_client/28_BankBalances.py rename to examples/chain_client/bank/query/2_BankBalances.py diff --git a/examples/chain_client/50_SpendableBalances.py b/examples/chain_client/bank/query/3_SpendableBalances.py similarity index 100% rename from examples/chain_client/50_SpendableBalances.py rename to examples/chain_client/bank/query/3_SpendableBalances.py diff --git a/examples/chain_client/51_SpendableBalancesByDenom.py b/examples/chain_client/bank/query/4_SpendableBalancesByDenom.py similarity index 100% rename from examples/chain_client/51_SpendableBalancesByDenom.py rename to examples/chain_client/bank/query/4_SpendableBalancesByDenom.py diff --git a/examples/chain_client/52_TotalSupply.py b/examples/chain_client/bank/query/5_TotalSupply.py similarity index 100% rename from examples/chain_client/52_TotalSupply.py rename to examples/chain_client/bank/query/5_TotalSupply.py diff --git a/examples/chain_client/53_SupplyOf.py b/examples/chain_client/bank/query/6_SupplyOf.py similarity index 100% rename from examples/chain_client/53_SupplyOf.py rename to examples/chain_client/bank/query/6_SupplyOf.py diff --git a/examples/chain_client/54_DenomMetadata.py b/examples/chain_client/bank/query/7_DenomMetadata.py similarity index 100% rename from examples/chain_client/54_DenomMetadata.py rename to examples/chain_client/bank/query/7_DenomMetadata.py diff --git a/examples/chain_client/55_DenomsMetadata.py b/examples/chain_client/bank/query/8_DenomsMetadata.py similarity index 100% rename from examples/chain_client/55_DenomsMetadata.py rename to examples/chain_client/bank/query/8_DenomsMetadata.py diff --git a/examples/chain_client/56_DenomOwners.py b/examples/chain_client/bank/query/9_DenomOwners.py similarity index 100% rename from examples/chain_client/56_DenomOwners.py rename to examples/chain_client/bank/query/9_DenomOwners.py diff --git a/examples/chain_client/distribution/1_SetWithdrawAddress.py b/examples/chain_client/distribution/1_SetWithdrawAddress.py new file mode 100644 index 00000000..b317a998 --- /dev/null +++ b/examples/chain_client/distribution/1_SetWithdrawAddress.py @@ -0,0 +1,46 @@ +import asyncio +import os + +import dotenv + +from pyinjective import AsyncClient, PrivateKey +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + 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()) + + withdraw_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + + message = composer.msg_set_withdraw_address( + delegator_address=address.to_acc_bech32(), + withdraw_address=withdraw_address, + ) + + # 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()) diff --git a/examples/chain_client/distribution/2_WithdrawDelegatorReward.py b/examples/chain_client/distribution/2_WithdrawDelegatorReward.py new file mode 100644 index 00000000..02facdc7 --- /dev/null +++ b/examples/chain_client/distribution/2_WithdrawDelegatorReward.py @@ -0,0 +1,47 @@ +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() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + 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 + validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" + + message = composer.msg_withdraw_delegator_reward( + delegator_address=address.to_acc_bech32(), validator_address=validator_address + ) + + # 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()) diff --git a/examples/chain_client/distribution/3_WithdrawValidatorCommission.py b/examples/chain_client/distribution/3_WithdrawValidatorCommission.py new file mode 100644 index 00000000..cd351d1f --- /dev/null +++ b/examples/chain_client/distribution/3_WithdrawValidatorCommission.py @@ -0,0 +1,45 @@ +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() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + 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 + validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" + + message = composer.msg_withdraw_validator_commission(validator_address=validator_address) + + # 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()) diff --git a/examples/chain_client/distribution/4_FundCommunityPool.py b/examples/chain_client/distribution/4_FundCommunityPool.py new file mode 100644 index 00000000..c60475c8 --- /dev/null +++ b/examples/chain_client/distribution/4_FundCommunityPool.py @@ -0,0 +1,47 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective import AsyncClient, PrivateKey +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + 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()) + + amount = composer.create_coin_amount(amount=Decimal("0.1"), token_name="INJ") + + message = composer.msg_fund_community_pool( + amounts=[amount], + depositor=address.to_acc_bech32(), + ) + + # 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()) diff --git a/examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py b/examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py new file mode 100644 index 00000000..13161630 --- /dev/null +++ b/examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py @@ -0,0 +1,16 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + distribution_info = await client.fetch_validator_distribution_info(validator_address=validator_address) + print(distribution_info) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py b/examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py new file mode 100644 index 00000000..31833682 --- /dev/null +++ b/examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py @@ -0,0 +1,16 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + rewards = await client.fetch_validator_outstanding_rewards(validator_address=validator_address) + print(rewards) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/query/3_ValidatorCommission.py b/examples/chain_client/distribution/query/3_ValidatorCommission.py new file mode 100644 index 00000000..a82e191b --- /dev/null +++ b/examples/chain_client/distribution/query/3_ValidatorCommission.py @@ -0,0 +1,16 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + commission = await client.fetch_validator_commission(validator_address=validator_address) + print(commission) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/query/4_ValidatorSlashes.py b/examples/chain_client/distribution/query/4_ValidatorSlashes.py new file mode 100644 index 00000000..08dbfea1 --- /dev/null +++ b/examples/chain_client/distribution/query/4_ValidatorSlashes.py @@ -0,0 +1,20 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + limit = 2 + pagination = PaginationOption(limit=limit) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + contracts = await client.fetch_validator_slashes(validator_address=validator_address, pagination=pagination) + print(contracts) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/query/5_DelegationRewards.py b/examples/chain_client/distribution/query/5_DelegationRewards.py new file mode 100644 index 00000000..da112263 --- /dev/null +++ b/examples/chain_client/distribution/query/5_DelegationRewards.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + validator_address = "injvaloper156t3yxd4udv0h9gwagfcmwnmm3quy0nph7tyh5" + rewards = await client.fetch_delegation_rewards( + delegator_address=delegator_address, validator_address=validator_address + ) + print(rewards) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/query/6_DelegationTotalRewards.py b/examples/chain_client/distribution/query/6_DelegationTotalRewards.py new file mode 100644 index 00000000..c67dc94f --- /dev/null +++ b/examples/chain_client/distribution/query/6_DelegationTotalRewards.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + rewards = await client.fetch_delegation_total_rewards( + delegator_address=delegator_address, + ) + print(rewards) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/query/7_DelegatorValidators.py b/examples/chain_client/distribution/query/7_DelegatorValidators.py new file mode 100644 index 00000000..f03fb8ec --- /dev/null +++ b/examples/chain_client/distribution/query/7_DelegatorValidators.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + validators = await client.fetch_delegator_validators( + delegator_address=delegator_address, + ) + print(validators) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py b/examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py new file mode 100644 index 00000000..d3c27091 --- /dev/null +++ b/examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + withdraw_address = await client.fetch_delegator_withdraw_address( + delegator_address=delegator_address, + ) + print(withdraw_address) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/query/9_CommunityPool.py b/examples/chain_client/distribution/query/9_CommunityPool.py new file mode 100644 index 00000000..7a803d03 --- /dev/null +++ b/examples/chain_client/distribution/query/9_CommunityPool.py @@ -0,0 +1,15 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + community_pool = await client.fetch_community_pool() + print(community_pool) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py similarity index 84% rename from examples/chain_client/7_MsgCreateDerivativeMarketOrder.py rename to examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py index 744b5ff9..4e0ff327 100644 --- a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py +++ b/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +14,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +26,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -31,15 +37,17 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateDerivativeMarketOrder( + msg = composer.msg_create_derivative_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=50000, - quantity=0.01, - leverage=3, - is_buy=True, + price=Decimal(50000), + quantity=Decimal(0.1), + margin=composer.calculate_margin( + quantity=Decimal(0.1), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ) @@ -71,7 +79,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py similarity index 84% rename from examples/chain_client/6_MsgCreateDerivativeLimitOrder.py rename to examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py index b875d339..7b561970 100644 --- a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +14,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +26,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -31,16 +37,17 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateDerivativeLimitOrder( + msg = composer.msg_create_derivative_market_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=50000, - quantity=0.1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(50000), + quantity=Decimal(0.1), + margin=composer.calculate_margin( + quantity=Decimal(0.1), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ) @@ -72,7 +79,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/8_MsgCancelDerivativeOrder.py b/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py similarity index 91% rename from examples/chain_client/8_MsgCancelDerivativeOrder.py rename to examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py index b784b536..20be2bd0 100644 --- a/examples/chain_client/8_MsgCancelDerivativeOrder.py +++ b/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -30,7 +35,7 @@ async def main() -> None: order_hash = "0x667ee6f37f6d06bf473f4e1434e92ac98ff43c785405e2a511a0843daeca2de9" # prepare tx msg - msg = composer.MsgCancelDerivativeOrder( + msg = composer.msg_cancel_derivative_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash ) @@ -58,7 +63,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py new file mode 100644 index 00000000..86e66b1a --- /dev/null +++ b/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py @@ -0,0 +1,60 @@ +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) + 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_instant_binary_options_market_launch( + sender=address.to_acc_bech32(), + ticker="UFC-KHABIB-TKO-05/30/2023", + oracle_symbol="UFC-KHABIB-TKO-05/30/2023", + oracle_provider="UFC", + oracle_type="Provider", + oracle_scale_factor=6, + maker_fee_rate=0.0005, # 0.05% + taker_fee_rate=0.0010, # 0.10% + expiration_timestamp=1680730982, + settlement_timestamp=1690730982, + admin=address.to_acc_bech32(), + quote_denom="peggy0xdAC17F958D2ee523a2206206994597C13D831ec7", + min_price_tick_size=0.01, + min_quantity_tick_size=0.01, + ) + + # 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()) diff --git a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py similarity index 88% rename from examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py rename to examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py index 137529ea..5ad8c59e 100644 --- a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py +++ b/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -12,6 +15,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -21,7 +27,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -35,17 +41,17 @@ async def main() -> None: denom = Denom(description="desc", base=0, quote=6, min_price_tick_size=1000, min_quantity_tick_size=0.0001) # prepare tx msg - msg = composer.MsgCreateBinaryOptionsLimitOrder( + msg = composer.msg_create_binary_options_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.5, - quantity=1, - is_buy=False, - is_reduce_only=False, - denom=denom, + price=Decimal("0.5"), + quantity=Decimal("1"), + margin=Decimal("0.5"), + order_type="BUY", cid=str(uuid.uuid4()), + denom=denom, ) # build sim tx @@ -76,7 +82,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py similarity index 84% rename from examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py rename to examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py index 67004f17..9b68bc85 100644 --- a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py +++ b/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +14,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +26,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -31,15 +37,16 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateBinaryOptionsMarketOrder( + msg = composer.msg_create_binary_options_market_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.5, - quantity=1, - is_buy=True, - is_reduce_only=False, + price=Decimal("0.5"), + quantity=Decimal(1), + margin=composer.calculate_margin( + quantity=Decimal(1), price=Decimal("0.5"), leverage=Decimal(1), is_reduce_only=False + ), cid=str(uuid.uuid4()), ) # build sim tx @@ -70,7 +77,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py similarity index 91% rename from examples/chain_client/33_MsgCancelBinaryOptionsOrder.py rename to examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py index 2631ab26..582c6dc6 100644 --- a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py +++ b/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -30,7 +35,7 @@ async def main() -> None: order_hash = "a975fbd72b874bdbf5caf5e1e8e2653937f33ce6dd14d241c06c8b1f7b56be46" # prepare tx msg - msg = composer.MsgCancelBinaryOptionsOrder( + msg = composer.msg_cancel_binary_options_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash ) # build sim tx @@ -61,7 +66,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/16_MsgSubaccountTransfer.py b/examples/chain_client/exchange/17_MsgSubaccountTransfer.py similarity index 89% rename from examples/chain_client/16_MsgSubaccountTransfer.py rename to examples/chain_client/exchange/17_MsgSubaccountTransfer.py index 5a18b1dd..a50fc0cf 100644 --- a/examples/chain_client/16_MsgSubaccountTransfer.py +++ b/examples/chain_client/exchange/17_MsgSubaccountTransfer.py @@ -1,5 +1,8 @@ import asyncio +import os +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -27,11 +33,11 @@ async def main() -> None: dest_subaccount_id = address.get_subaccount_id(index=1) # prepare tx msg - msg = composer.MsgSubaccountTransfer( + msg = composer.msg_subaccount_transfer( sender=address.to_acc_bech32(), source_subaccount_id=subaccount_id, destination_subaccount_id=dest_subaccount_id, - amount=100, + amount=Decimal(100), denom="INJ", ) @@ -59,7 +65,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/30_ExternalTransfer.py b/examples/chain_client/exchange/18_MsgExternalTransfer.py similarity index 89% rename from examples/chain_client/30_ExternalTransfer.py rename to examples/chain_client/exchange/18_MsgExternalTransfer.py index d657c15a..2bcc86a1 100644 --- a/examples/chain_client/30_ExternalTransfer.py +++ b/examples/chain_client/exchange/18_MsgExternalTransfer.py @@ -1,5 +1,8 @@ import asyncio +import os +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -27,11 +33,11 @@ async def main() -> None: dest_subaccount_id = "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000" # prepare tx msg - msg = composer.MsgExternalTransfer( + msg = composer.msg_external_transfer( sender=address.to_acc_bech32(), source_subaccount_id=subaccount_id, destination_subaccount_id=dest_subaccount_id, - amount=100, + amount=Decimal(100), denom="INJ", ) @@ -59,7 +65,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/77_MsgLiquidatePosition.py b/examples/chain_client/exchange/19_MsgLiquidatePosition.py similarity index 83% rename from examples/chain_client/77_MsgLiquidatePosition.py rename to examples/chain_client/exchange/19_MsgLiquidatePosition.py index 65e7f12b..9788b865 100644 --- a/examples/chain_client/77_MsgLiquidatePosition.py +++ b/examples/chain_client/exchange/19_MsgLiquidatePosition.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +14,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +26,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -31,19 +37,21 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" cid = str(uuid.uuid4()) - order = composer.DerivativeOrder( + order = composer.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=39.01, # This should be the liquidation price - quantity=0.147, - leverage=1, + price=Decimal(39.01), # This should be the liquidation price + quantity=Decimal(0.147), + margin=composer.calculate_margin( + quantity=Decimal(0.147), price=Decimal(39.01), leverage=Decimal(1), is_reduce_only=False + ), + order_type="SELL", cid=cid, - is_buy=False, ) # prepare tx msg - msg = composer.MsgLiquidatePosition( + msg = composer.msg_liquidate_position( sender=address.to_acc_bech32(), subaccount_id="0x156df4d5bc8e7dd9191433e54bd6a11eeb390921000000000000000000000000", market_id=market_id, @@ -78,7 +86,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/2_MsgDeposit.py b/examples/chain_client/exchange/1_MsgDeposit.py similarity index 85% rename from examples/chain_client/2_MsgDeposit.py rename to examples/chain_client/exchange/1_MsgDeposit.py index 9c137b49..bbf64710 100644 --- a/examples/chain_client/2_MsgDeposit.py +++ b/examples/chain_client/exchange/1_MsgDeposit.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,8 +12,11 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet - network = Network.testnet(node="sentry") + network = Network.testnet() # initialize grpc client client = AsyncClient(network) @@ -19,14 +24,16 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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 tx msg - msg = composer.MsgDeposit(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=0.000001, denom="INJ") + msg = composer.msg_deposit( + sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=0.000001, denom="INJ" + ) # build sim tx tx = ( @@ -52,7 +59,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/13_MsgIncreasePositionMargin.py b/examples/chain_client/exchange/20_MsgIncreasePositionMargin.py similarity index 89% rename from examples/chain_client/13_MsgIncreasePositionMargin.py rename to examples/chain_client/exchange/20_MsgIncreasePositionMargin.py index 27d42884..276276e7 100644 --- a/examples/chain_client/13_MsgIncreasePositionMargin.py +++ b/examples/chain_client/exchange/20_MsgIncreasePositionMargin.py @@ -1,5 +1,8 @@ import asyncio +import os +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -29,12 +35,12 @@ async def main() -> None: market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" # prepare tx msg - msg = composer.MsgIncreasePositionMargin( + msg = composer.msg_increase_position_margin( sender=address.to_acc_bech32(), market_id=market_id, source_subaccount_id=subaccount_id, destination_subaccount_id=subaccount_id, - amount=2, + amount=Decimal(2), ) # build sim tx @@ -61,7 +67,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/24_MsgRewardsOptOut.py b/examples/chain_client/exchange/21_MsgRewardsOptOut.py similarity index 89% rename from examples/chain_client/24_MsgRewardsOptOut.py rename to examples/chain_client/exchange/21_MsgRewardsOptOut.py index bbc8d348..2306b541 100644 --- a/examples/chain_client/24_MsgRewardsOptOut.py +++ b/examples/chain_client/exchange/21_MsgRewardsOptOut.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,13 +24,13 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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 - msg = composer.MsgRewardsOptOut(sender=address.to_acc_bech32()) + msg = composer.msg_rewards_opt_out(sender=address.to_acc_bech32()) # build sim tx tx = ( @@ -51,7 +56,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py b/examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py similarity index 89% rename from examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py rename to examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py index d9eb1e18..b638b28a 100644 --- a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py +++ b/examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py @@ -1,5 +1,8 @@ import asyncio +import os +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -27,12 +33,12 @@ async def main() -> None: # prepare trade info market_id = "0xfafec40a7b93331c1fc89c23f66d11fbb48f38dfdd78f7f4fc4031fad90f6896" status = "Demolished" - settlement_price = 1 + settlement_price = Decimal(1) expiration_timestamp = 1685460582 settlement_timestamp = 1690730982 # prepare tx msg - msg = composer.MsgAdminUpdateBinaryOptionsMarket( + msg = composer.msg_admin_update_binary_options_market( sender=address.to_acc_bech32(), market_id=market_id, settlement_price=settlement_price, @@ -69,7 +75,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/15_MsgWithdraw.py b/examples/chain_client/exchange/2_MsgWithdraw.py similarity index 87% rename from examples/chain_client/15_MsgWithdraw.py rename to examples/chain_client/exchange/2_MsgWithdraw.py index 9fc1e359..1070d28c 100644 --- a/examples/chain_client/15_MsgWithdraw.py +++ b/examples/chain_client/exchange/2_MsgWithdraw.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,14 +24,14 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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 tx msg - msg = composer.MsgWithdraw(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom="USDT") + msg = composer.msg_withdraw(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom="USDT") # build sim tx tx = ( @@ -52,7 +57,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py b/examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py new file mode 100644 index 00000000..90a177ec --- /dev/null +++ b/examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py @@ -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_instant_spot_market_launch( + sender=address.to_acc_bech32(), + ticker="INJ/USDC", + base_denom="INJ", + quote_denom="USDC", + min_price_tick_size=Decimal("0.001"), + min_quantity_tick_size=Decimal("0.01"), + ) + + # 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()) diff --git a/examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py b/examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py new file mode 100644 index 00000000..b2b5dff4 --- /dev/null +++ b/examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py @@ -0,0 +1,61 @@ +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_instant_perpetual_market_launch( + sender=address.to_acc_bech32(), + ticker="INJ/USDC PERP", + quote_denom="USDC", + oracle_base="INJ", + oracle_quote="USDC", + oracle_scale_factor=6, + oracle_type="Band", + maker_fee_rate=Decimal("-0.0001"), + taker_fee_rate=Decimal("0.001"), + initial_margin_ratio=Decimal("0.33"), + maintenance_margin_ratio=Decimal("0.095"), + min_price_tick_size=Decimal("0.001"), + min_quantity_tick_size=Decimal("0.01"), + ) + + # 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()) diff --git a/examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py b/examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py new file mode 100644 index 00000000..d451fd15 --- /dev/null +++ b/examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py @@ -0,0 +1,62 @@ +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_instant_expiry_futures_market_launch( + sender=address.to_acc_bech32(), + ticker="INJ/USDC FUT", + quote_denom="USDC", + oracle_base="INJ", + oracle_quote="USDC", + oracle_scale_factor=6, + oracle_type="Band", + expiry=2000000000, + maker_fee_rate=Decimal("-0.0001"), + taker_fee_rate=Decimal("0.001"), + initial_margin_ratio=Decimal("0.33"), + maintenance_margin_ratio=Decimal("0.095"), + min_price_tick_size=Decimal("0.001"), + min_quantity_tick_size=Decimal("0.01"), + ) + + # 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()) diff --git a/examples/chain_client/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py similarity index 88% rename from examples/chain_client/3_MsgCreateSpotLimitOrder.py rename to examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py index 8d873354..5b3b966a 100644 --- a/examples/chain_client/3_MsgCreateSpotLimitOrder.py +++ b/examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +14,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +26,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -32,15 +38,14 @@ async def main() -> None: cid = str(uuid.uuid4()) # prepare tx msg - msg = composer.MsgCreateSpotLimitOrder( + msg = composer.msg_create_spot_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=cid, ) @@ -72,7 +77,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py similarity index 88% rename from examples/chain_client/4_MsgCreateSpotMarketOrder.py rename to examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py index d689362f..36ea27de 100644 --- a/examples/chain_client/4_MsgCreateSpotMarketOrder.py +++ b/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +14,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +26,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -31,14 +37,14 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateSpotMarketOrder( - sender=address.to_acc_bech32(), + msg = composer.msg_create_spot_market_order( market_id=market_id, + sender=address.to_acc_bech32(), subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=10.522, - quantity=0.01, - is_buy=True, + price=Decimal("10.522"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) @@ -70,7 +76,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/5_MsgCancelSpotOrder.py b/examples/chain_client/exchange/8_MsgCancelSpotOrder.py similarity index 92% rename from examples/chain_client/5_MsgCancelSpotOrder.py rename to examples/chain_client/exchange/8_MsgCancelSpotOrder.py index a6fabc01..970b2190 100644 --- a/examples/chain_client/5_MsgCancelSpotOrder.py +++ b/examples/chain_client/exchange/8_MsgCancelSpotOrder.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -58,7 +63,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/17_MsgBatchUpdateOrders.py b/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py similarity index 80% rename from examples/chain_client/17_MsgBatchUpdateOrders.py rename to examples/chain_client/exchange/9_MsgBatchUpdateOrders.py index 25147452..04e41058 100644 --- a/examples/chain_client/17_MsgBatchUpdateOrders.py +++ b/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +from decimal import Decimal +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +14,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +26,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -38,12 +44,12 @@ async def main() -> None: spot_market_id_cancel_2 = "0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0" derivative_orders_to_cancel = [ - composer.OrderData( + composer.order_data( market_id=derivative_market_id_cancel, subaccount_id=subaccount_id, order_hash="0x48690013c382d5dbaff9989db04629a16a5818d7524e027d517ccc89fd068103", ), - composer.OrderData( + composer.order_data( market_id=derivative_market_id_cancel_2, subaccount_id=subaccount_id, order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -51,12 +57,12 @@ async def main() -> None: ] spot_orders_to_cancel = [ - composer.OrderData( + composer.order_data( market_id=spot_market_id_cancel, subaccount_id=subaccount_id, cid="0e5c3ad5-2cc4-4a2a-bbe5-b12697739163", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id_cancel_2, subaccount_id=subaccount_id, order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", @@ -64,49 +70,49 @@ async def main() -> None: ] derivative_orders_to_create = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=derivative_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=25000, - quantity=0.1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(25000), + quantity=Decimal(0.1), + margin=composer.calculate_margin( + quantity=Decimal(0.1), price=Decimal(25000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.DerivativeOrder( + composer.derivative_order( market_id=derivative_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=50000, - quantity=0.01, - leverage=1, - is_buy=False, - is_po=False, + price=Decimal(50000), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ), ] spot_orders_to_create = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=3, - quantity=55, - is_buy=True, - is_po=False, + price=Decimal("3"), + quantity=Decimal("55"), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=300, - quantity=55, - is_buy=False, - is_po=False, + price=Decimal("300"), + quantity=Decimal("55"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] @@ -148,7 +154,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/exchange/query/10_SpotMarkets.py b/examples/chain_client/exchange/query/10_SpotMarkets.py new file mode 100644 index 00000000..4cedc9d7 --- /dev/null +++ b/examples/chain_client/exchange/query/10_SpotMarkets.py @@ -0,0 +1,22 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_markets = await client.fetch_chain_spot_markets( + status="Active", + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(spot_markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/11_SpotMarket.py b/examples/chain_client/exchange/query/11_SpotMarket.py new file mode 100644 index 00000000..0e774edf --- /dev/null +++ b/examples/chain_client/exchange/query/11_SpotMarket.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_market = await client.fetch_chain_spot_market( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(spot_market) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/12_FullSpotMarkets.py b/examples/chain_client/exchange/query/12_FullSpotMarkets.py new file mode 100644 index 00000000..cfefee28 --- /dev/null +++ b/examples/chain_client/exchange/query/12_FullSpotMarkets.py @@ -0,0 +1,23 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_markets = await client.fetch_chain_full_spot_markets( + status="Active", + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + with_mid_price_and_tob=True, + ) + print(spot_markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/13_FullSpotMarket.py b/examples/chain_client/exchange/query/13_FullSpotMarket.py new file mode 100644 index 00000000..6a39269d --- /dev/null +++ b/examples/chain_client/exchange/query/13_FullSpotMarket.py @@ -0,0 +1,22 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_market = await client.fetch_chain_full_spot_market( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + with_mid_price_and_tob=True, + ) + print(spot_market) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/14_SpotOrderbook.py b/examples/chain_client/exchange/query/14_SpotOrderbook.py new file mode 100644 index 00000000..7b5a9aa1 --- /dev/null +++ b/examples/chain_client/exchange/query/14_SpotOrderbook.py @@ -0,0 +1,26 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + pagination = PaginationOption(limit=2) + + orderbook = await client.fetch_chain_spot_orderbook( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + order_side="Buy", + pagination=pagination, + ) + print(orderbook) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/15_TraderSpotOrders.py b/examples/chain_client/exchange/query/15_TraderSpotOrders.py new file mode 100644 index 00000000..0cc96b6f --- /dev/null +++ b/examples/chain_client/exchange/query/15_TraderSpotOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + orders = await client.fetch_chain_trader_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py b/examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py new file mode 100644 index 00000000..8e50fa95 --- /dev/null +++ b/examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py @@ -0,0 +1,35 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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()) + + orders = await client.fetch_chain_account_address_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + account_address=address.to_acc_bech32(), + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/17_SpotOrdersByHashes.py b/examples/chain_client/exchange/query/17_SpotOrdersByHashes.py new file mode 100644 index 00000000..641eb6f5 --- /dev/null +++ b/examples/chain_client/exchange/query/17_SpotOrdersByHashes.py @@ -0,0 +1,38 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + orders = await client.fetch_chain_spot_orders_by_hashes( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id=subaccount_id, + order_hashes=["0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"], + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/18_SubaccountOrders.py b/examples/chain_client/exchange/query/18_SubaccountOrders.py new file mode 100644 index 00000000..4983f827 --- /dev/null +++ b/examples/chain_client/exchange/query/18_SubaccountOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + orders = await client.fetch_chain_subaccount_orders( + subaccount_id=subaccount_id, + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py b/examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py new file mode 100644 index 00000000..2b29c2c0 --- /dev/null +++ b/examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + orders = await client.fetch_chain_trader_spot_transient_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/1_SubaccountDeposits.py b/examples/chain_client/exchange/query/1_SubaccountDeposits.py new file mode 100644 index 00000000..f9afb8ae --- /dev/null +++ b/examples/chain_client/exchange/query/1_SubaccountDeposits.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + deposits = await client.fetch_subaccount_deposits(subaccount_id=subaccount_id) + print(deposits) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py b/examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py new file mode 100644 index 00000000..35493ffd --- /dev/null +++ b/examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + prices = await client.fetch_spot_mid_price_and_tob( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(prices) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py b/examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py new file mode 100644 index 00000000..5b5c5fff --- /dev/null +++ b/examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + prices = await client.fetch_derivative_mid_price_and_tob( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(prices) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/22_DerivativeOrderbook.py b/examples/chain_client/exchange/query/22_DerivativeOrderbook.py new file mode 100644 index 00000000..465a62b6 --- /dev/null +++ b/examples/chain_client/exchange/query/22_DerivativeOrderbook.py @@ -0,0 +1,25 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + pagination = PaginationOption(limit=2) + + orderbook = await client.fetch_chain_derivative_orderbook( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + pagination=pagination, + ) + print(orderbook) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py b/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py new file mode 100644 index 00000000..244a61b4 --- /dev/null +++ b/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + orders = await client.fetch_chain_trader_derivative_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py b/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py new file mode 100644 index 00000000..2ecc6e2d --- /dev/null +++ b/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py @@ -0,0 +1,35 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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()) + + orders = await client.fetch_chain_account_address_derivative_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + account_address=address.to_acc_bech32(), + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py b/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py new file mode 100644 index 00000000..825f5523 --- /dev/null +++ b/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py @@ -0,0 +1,38 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + orders = await client.fetch_chain_derivative_orders_by_hashes( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id=subaccount_id, + order_hashes=["0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"], + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py b/examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py new file mode 100644 index 00000000..c5548d59 --- /dev/null +++ b/examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + orders = await client.fetch_chain_trader_derivative_transient_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/27_DerivativeMarkets.py b/examples/chain_client/exchange/query/27_DerivativeMarkets.py new file mode 100644 index 00000000..2f4bbc5a --- /dev/null +++ b/examples/chain_client/exchange/query/27_DerivativeMarkets.py @@ -0,0 +1,22 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + derivative_markets = await client.fetch_chain_derivative_markets( + status="Active", + market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"], + ) + print(derivative_markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/28_DerivativeMarket.py b/examples/chain_client/exchange/query/28_DerivativeMarket.py new file mode 100644 index 00000000..152381f5 --- /dev/null +++ b/examples/chain_client/exchange/query/28_DerivativeMarket.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + derivative_market = await client.fetch_chain_derivative_market( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(derivative_market) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/29_DerivativeMarketAddress.py b/examples/chain_client/exchange/query/29_DerivativeMarketAddress.py new file mode 100644 index 00000000..c2d88805 --- /dev/null +++ b/examples/chain_client/exchange/query/29_DerivativeMarketAddress.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + address = await client.fetch_derivative_market_address( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(address) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/2_SubaccountDeposit.py b/examples/chain_client/exchange/query/2_SubaccountDeposit.py new file mode 100644 index 00000000..5002397d --- /dev/null +++ b/examples/chain_client/exchange/query/2_SubaccountDeposit.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + deposit = await client.fetch_subaccount_deposit(subaccount_id=subaccount_id, denom="inj") + print(deposit) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/30_SubaccountTradeNonce.py b/examples/chain_client/exchange/query/30_SubaccountTradeNonce.py new file mode 100644 index 00000000..ad81aca3 --- /dev/null +++ b/examples/chain_client/exchange/query/30_SubaccountTradeNonce.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + nonce = await client.fetch_subaccount_trade_nonce( + subaccount_id=subaccount_id, + ) + print(nonce) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/31_Positions.py b/examples/chain_client/exchange/query/31_Positions.py new file mode 100644 index 00000000..ae494b6a --- /dev/null +++ b/examples/chain_client/exchange/query/31_Positions.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + positions = await client.fetch_chain_positions() + print(positions) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/32_SubaccountPositions.py b/examples/chain_client/exchange/query/32_SubaccountPositions.py new file mode 100644 index 00000000..000d95b6 --- /dev/null +++ b/examples/chain_client/exchange/query/32_SubaccountPositions.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + positions = await client.fetch_chain_subaccount_positions( + subaccount_id=subaccount_id, + ) + print(positions) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/33_SubaccountPositionInMarket.py b/examples/chain_client/exchange/query/33_SubaccountPositionInMarket.py new file mode 100644 index 00000000..4e0f1ddb --- /dev/null +++ b/examples/chain_client/exchange/query/33_SubaccountPositionInMarket.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + position = await client.fetch_chain_subaccount_position_in_market( + subaccount_id=subaccount_id, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(position) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/34_SubaccountEffectivePositionInMarket.py b/examples/chain_client/exchange/query/34_SubaccountEffectivePositionInMarket.py new file mode 100644 index 00000000..e729e77c --- /dev/null +++ b/examples/chain_client/exchange/query/34_SubaccountEffectivePositionInMarket.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + position = await client.fetch_chain_subaccount_effective_position_in_market( + subaccount_id=subaccount_id, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(position) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/35_PerpetualMarketInfo.py b/examples/chain_client/exchange/query/35_PerpetualMarketInfo.py new file mode 100644 index 00000000..ca27f552 --- /dev/null +++ b/examples/chain_client/exchange/query/35_PerpetualMarketInfo.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_info = await client.fetch_chain_perpetual_market_info( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(market_info) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py b/examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py new file mode 100644 index 00000000..4053013c --- /dev/null +++ b/examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_info = await client.fetch_chain_expiry_futures_market_info( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(market_info) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/37_PerpetualMarketFunding.py b/examples/chain_client/exchange/query/37_PerpetualMarketFunding.py new file mode 100644 index 00000000..099c2a0f --- /dev/null +++ b/examples/chain_client/exchange/query/37_PerpetualMarketFunding.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + funding = await client.fetch_chain_perpetual_market_funding( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(funding) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py b/examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py new file mode 100644 index 00000000..f4af9d38 --- /dev/null +++ b/examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + metadata = await client.fetch_subaccount_order_metadata( + subaccount_id=subaccount_id, + ) + print(metadata) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/39_TradeRewardPoints.py b/examples/chain_client/exchange/query/39_TradeRewardPoints.py new file mode 100644 index 00000000..13f08730 --- /dev/null +++ b/examples/chain_client/exchange/query/39_TradeRewardPoints.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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()) + + points = await client.fetch_trade_reward_points( + accounts=[address.to_acc_bech32()], + ) + print(points) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/3_ExchangeBalances.py b/examples/chain_client/exchange/query/3_ExchangeBalances.py new file mode 100644 index 00000000..091bf10c --- /dev/null +++ b/examples/chain_client/exchange/query/3_ExchangeBalances.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + # initialize grpc client + client = AsyncClient(network) + + balances = await client.fetch_exchange_balances() + print(balances) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py b/examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py new file mode 100644 index 00000000..fa3e8aa2 --- /dev/null +++ b/examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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()) + + points = await client.fetch_pending_trade_reward_points( + accounts=[address.to_acc_bech32()], + ) + print(points) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/41_TradeRewardCampaign.py b/examples/chain_client/exchange/query/41_TradeRewardCampaign.py new file mode 100644 index 00000000..33e45a7e --- /dev/null +++ b/examples/chain_client/exchange/query/41_TradeRewardCampaign.py @@ -0,0 +1,32 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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()) + + campaign = await client.fetch_trade_reward_campaign() + print(campaign) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/42_FeeDiscountAccountInfo.py b/examples/chain_client/exchange/query/42_FeeDiscountAccountInfo.py new file mode 100644 index 00000000..15fbb7ce --- /dev/null +++ b/examples/chain_client/exchange/query/42_FeeDiscountAccountInfo.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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()) + + fee_discount = await client.fetch_fee_discount_account_info( + account=address.to_acc_bech32(), + ) + print(fee_discount) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/43_FeeDiscountSchedule.py b/examples/chain_client/exchange/query/43_FeeDiscountSchedule.py new file mode 100644 index 00000000..a0ae96cb --- /dev/null +++ b/examples/chain_client/exchange/query/43_FeeDiscountSchedule.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + schedule = await client.fetch_fee_discount_schedule() + print(schedule) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/44_BalanceMismatches.py b/examples/chain_client/exchange/query/44_BalanceMismatches.py new file mode 100644 index 00000000..c7f7ca5e --- /dev/null +++ b/examples/chain_client/exchange/query/44_BalanceMismatches.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + mismatches = await client.fetch_balance_mismatches(dust_factor=1) + print(mismatches) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/45_BalanceWithBalanceHolds.py b/examples/chain_client/exchange/query/45_BalanceWithBalanceHolds.py new file mode 100644 index 00000000..6587c59a --- /dev/null +++ b/examples/chain_client/exchange/query/45_BalanceWithBalanceHolds.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + balance = await client.fetch_balance_with_balance_holds() + print(balance) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/46_FeeDiscountTierStatistics.py b/examples/chain_client/exchange/query/46_FeeDiscountTierStatistics.py new file mode 100644 index 00000000..5671e4ce --- /dev/null +++ b/examples/chain_client/exchange/query/46_FeeDiscountTierStatistics.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + statistics = await client.fetch_fee_discount_tier_statistics() + print(statistics) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/47_MitoVaultInfos.py b/examples/chain_client/exchange/query/47_MitoVaultInfos.py new file mode 100644 index 00000000..3faa5cb9 --- /dev/null +++ b/examples/chain_client/exchange/query/47_MitoVaultInfos.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + infos = await client.fetch_mito_vault_infos() + print(infos) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/48_QueryMarketIDFromVault.py b/examples/chain_client/exchange/query/48_QueryMarketIDFromVault.py new file mode 100644 index 00000000..e699dbaa --- /dev/null +++ b/examples/chain_client/exchange/query/48_QueryMarketIDFromVault.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_id = await client.fetch_market_id_from_vault(vault_address="inj1qg5ega6dykkxc307y25pecuufrjkxkag6xhp6y") + print(market_id) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/49_HistoricalTradeRecords.py b/examples/chain_client/exchange/query/49_HistoricalTradeRecords.py new file mode 100644 index 00000000..6b93200f --- /dev/null +++ b/examples/chain_client/exchange/query/49_HistoricalTradeRecords.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + records = await client.fetch_historical_trade_records( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + ) + print(records) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/4_AggregateVolume.py b/examples/chain_client/exchange/query/4_AggregateVolume.py new file mode 100644 index 00000000..35c334a5 --- /dev/null +++ b/examples/chain_client/exchange/query/4_AggregateVolume.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + + subaccount_id = address.get_subaccount_id(index=0) + + volume = await client.fetch_aggregate_volume(account=address.to_acc_bech32()) + print(volume) + + volume = await client.fetch_aggregate_volume(account=subaccount_id) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/50_IsOptedOutOfRewards.py b/examples/chain_client/exchange/query/50_IsOptedOutOfRewards.py new file mode 100644 index 00000000..28c0925c --- /dev/null +++ b/examples/chain_client/exchange/query/50_IsOptedOutOfRewards.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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()) + + is_opted_out = await client.fetch_is_opted_out_of_rewards( + account=address.to_acc_bech32(), + ) + print(is_opted_out) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/51_OptedOutOfRewardsAccounts.py b/examples/chain_client/exchange/query/51_OptedOutOfRewardsAccounts.py new file mode 100644 index 00000000..9940f799 --- /dev/null +++ b/examples/chain_client/exchange/query/51_OptedOutOfRewardsAccounts.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + opted_out = await client.fetch_opted_out_of_rewards_accounts() + print(opted_out) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/52_MarketVolatility.py b/examples/chain_client/exchange/query/52_MarketVolatility.py new file mode 100644 index 00000000..3173ca39 --- /dev/null +++ b/examples/chain_client/exchange/query/52_MarketVolatility.py @@ -0,0 +1,30 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + trade_grouping_sec = 10 + max_age = 0 + include_raw_history = True + include_metadata = True + volatility = await client.fetch_market_volatility( + market_id=market_id, + trade_grouping_sec=trade_grouping_sec, + max_age=max_age, + include_raw_history=include_raw_history, + include_metadata=include_metadata, + ) + print(volatility) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/53_BinaryOptionsMarkets.py b/examples/chain_client/exchange/query/53_BinaryOptionsMarkets.py new file mode 100644 index 00000000..4448a4ec --- /dev/null +++ b/examples/chain_client/exchange/query/53_BinaryOptionsMarkets.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + markets = await client.fetch_chain_binary_options_markets(status="Active") + print(markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/54_TraderDerivativeConditionalOrders.py b/examples/chain_client/exchange/query/54_TraderDerivativeConditionalOrders.py new file mode 100644 index 00000000..fd65e68f --- /dev/null +++ b/examples/chain_client/exchange/query/54_TraderDerivativeConditionalOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # 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) + + orders = await client.fetch_trader_derivative_conditional_orders( + subaccount_id=subaccount_id, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/55_MarketAtomicExecutionFeeMultiplier.py b/examples/chain_client/exchange/query/55_MarketAtomicExecutionFeeMultiplier.py new file mode 100644 index 00000000..328028d3 --- /dev/null +++ b/examples/chain_client/exchange/query/55_MarketAtomicExecutionFeeMultiplier.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + multiplier = await client.fetch_market_atomic_execution_fee_multiplier( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(multiplier) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/5_AggregateVolumes.py b/examples/chain_client/exchange/query/5_AggregateVolumes.py new file mode 100644 index 00000000..6effe4be --- /dev/null +++ b/examples/chain_client/exchange/query/5_AggregateVolumes.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +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) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + + volume = await client.fetch_aggregate_volumes( + accounts=[address.to_acc_bech32()], + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/6_AggregateMarketVolume.py b/examples/chain_client/exchange/query/6_AggregateMarketVolume.py new file mode 100644 index 00000000..b3262d82 --- /dev/null +++ b/examples/chain_client/exchange/query/6_AggregateMarketVolume.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + + volume = await client.fetch_aggregate_market_volume(market_id=market_id) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/7_AggregateMarketVolumes.py b/examples/chain_client/exchange/query/7_AggregateMarketVolumes.py new file mode 100644 index 00000000..23dfa0ec --- /dev/null +++ b/examples/chain_client/exchange/query/7_AggregateMarketVolumes.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + volume = await client.fetch_aggregate_market_volumes( + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/8_DenomDecimal.py b/examples/chain_client/exchange/query/8_DenomDecimal.py new file mode 100644 index 00000000..2079f5e8 --- /dev/null +++ b/examples/chain_client/exchange/query/8_DenomDecimal.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + deposits = await client.fetch_denom_decimal(denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5") + print(deposits) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/9_DenomDecimals.py b/examples/chain_client/exchange/query/9_DenomDecimals.py new file mode 100644 index 00000000..d96df30b --- /dev/null +++ b/examples/chain_client/exchange/query/9_DenomDecimals.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + deposits = await client.fetch_denom_decimals(denoms=["inj", "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"]) + print(deposits) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/41_MsgCreateInsuranceFund.py b/examples/chain_client/insurance/1_MsgCreateInsuranceFund.py similarity index 92% rename from examples/chain_client/41_MsgCreateInsuranceFund.py rename to examples/chain_client/insurance/1_MsgCreateInsuranceFund.py index b402dc26..99c10fc0 100644 --- a/examples/chain_client/41_MsgCreateInsuranceFund.py +++ b/examples/chain_client/insurance/1_MsgCreateInsuranceFund.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -60,7 +65,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/42_MsgUnderwrite.py b/examples/chain_client/insurance/2_MsgUnderwrite.py similarity index 92% rename from examples/chain_client/42_MsgUnderwrite.py rename to examples/chain_client/insurance/2_MsgUnderwrite.py index 9a14b3ce..16b75e70 100644 --- a/examples/chain_client/42_MsgUnderwrite.py +++ b/examples/chain_client/insurance/2_MsgUnderwrite.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -56,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/43_MsgRequestRedemption.py b/examples/chain_client/insurance/3_MsgRequestRedemption.py similarity index 92% rename from examples/chain_client/43_MsgRequestRedemption.py rename to examples/chain_client/insurance/3_MsgRequestRedemption.py index 6ba0fe31..ecc2793c 100644 --- a/examples/chain_client/43_MsgRequestRedemption.py +++ b/examples/chain_client/insurance/3_MsgRequestRedemption.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -56,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/23_MsgRelayPriceFeedPrice.py b/examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py similarity index 92% rename from examples/chain_client/23_MsgRelayPriceFeedPrice.py rename to examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py index 38b389de..b59b34a3 100644 --- a/examples/chain_client/23_MsgRelayPriceFeedPrice.py +++ b/examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -56,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/36_MsgRelayProviderPrices.py b/examples/chain_client/oracle/2_MsgRelayProviderPrices.py similarity index 92% rename from examples/chain_client/36_MsgRelayProviderPrices.py rename to examples/chain_client/oracle/2_MsgRelayProviderPrices.py index 0fb26b4f..1e3b9c8f 100644 --- a/examples/chain_client/36_MsgRelayProviderPrices.py +++ b/examples/chain_client/oracle/2_MsgRelayProviderPrices.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -61,7 +66,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/22_MsgSendToEth.py b/examples/chain_client/peggy/1_MsgSendToEth.py similarity index 93% rename from examples/chain_client/22_MsgSendToEth.py rename to examples/chain_client/peggy/1_MsgSendToEth.py index 1cb1e677..06e2d78c 100644 --- a/examples/chain_client/22_MsgSendToEth.py +++ b/examples/chain_client/peggy/1_MsgSendToEth.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv import requests from grpc import RpcError @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -65,7 +70,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/25_MsgDelegate.py b/examples/chain_client/staking/1_MsgDelegate.py similarity index 92% rename from examples/chain_client/25_MsgDelegate.py rename to examples/chain_client/staking/1_MsgDelegate.py index dc95f035..e32f6691 100644 --- a/examples/chain_client/25_MsgDelegate.py +++ b/examples/chain_client/staking/1_MsgDelegate.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -56,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/71_CreateDenom.py b/examples/chain_client/tokenfactory/1_CreateDenom.py similarity index 90% rename from examples/chain_client/71_CreateDenom.py rename to examples/chain_client/tokenfactory/1_CreateDenom.py index 61e76dbf..0662439a 100644 --- a/examples/chain_client/71_CreateDenom.py +++ b/examples/chain_client/tokenfactory/1_CreateDenom.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/72_MsgMint.py b/examples/chain_client/tokenfactory/2_MsgMint.py similarity index 85% rename from examples/chain_client/72_MsgMint.py rename to examples/chain_client/tokenfactory/2_MsgMint.py index e96bad93..b6617431 100644 --- a/examples/chain_client/72_MsgMint.py +++ b/examples/chain_client/tokenfactory/2_MsgMint.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, @@ -21,7 +26,7 @@ async def main() -> None: pub_key = priv_key.to_public_key() address = pub_key.to_address() - amount = composer.Coin(amount=1_000_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") + amount = composer.coin(amount=1_000_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") message = composer.msg_mint( sender=address.to_acc_bech32(), diff --git a/examples/chain_client/73_MsgBurn.py b/examples/chain_client/tokenfactory/3_MsgBurn.py similarity index 85% rename from examples/chain_client/73_MsgBurn.py rename to examples/chain_client/tokenfactory/3_MsgBurn.py index cff5a1b4..c4aa013a 100644 --- a/examples/chain_client/73_MsgBurn.py +++ b/examples/chain_client/tokenfactory/3_MsgBurn.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, @@ -21,7 +26,7 @@ async def main() -> None: pub_key = priv_key.to_public_key() address = pub_key.to_address() - amount = composer.Coin(amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") + amount = composer.coin(amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") message = composer.msg_burn( sender=address.to_acc_bech32(), diff --git a/examples/chain_client/75_MsgChangeAdmin.py b/examples/chain_client/tokenfactory/4_MsgChangeAdmin.py similarity index 91% rename from examples/chain_client/75_MsgChangeAdmin.py rename to examples/chain_client/tokenfactory/4_MsgChangeAdmin.py index 2abc6ec6..d1a1ba46 100644 --- a/examples/chain_client/75_MsgChangeAdmin.py +++ b/examples/chain_client/tokenfactory/4_MsgChangeAdmin.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( network=network, diff --git a/examples/chain_client/74_MsgSetDenomMetadata.py b/examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py similarity index 93% rename from examples/chain_client/74_MsgSetDenomMetadata.py rename to examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py index 58fa30c0..367649e0 100644 --- a/examples/chain_client/74_MsgSetDenomMetadata.py +++ b/examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( network=network, diff --git a/examples/chain_client/68_DenomAuthorityMetadata.py b/examples/chain_client/tokenfactory/query/1_DenomAuthorityMetadata.py similarity index 100% rename from examples/chain_client/68_DenomAuthorityMetadata.py rename to examples/chain_client/tokenfactory/query/1_DenomAuthorityMetadata.py diff --git a/examples/chain_client/69_DenomsFromCreator.py b/examples/chain_client/tokenfactory/query/2_DenomsFromCreator.py similarity index 100% rename from examples/chain_client/69_DenomsFromCreator.py rename to examples/chain_client/tokenfactory/query/2_DenomsFromCreator.py diff --git a/examples/chain_client/70_TokenfactoryModuleState.py b/examples/chain_client/tokenfactory/query/3_TokenfactoryModuleState.py similarity index 100% rename from examples/chain_client/70_TokenfactoryModuleState.py rename to examples/chain_client/tokenfactory/query/3_TokenfactoryModuleState.py diff --git a/examples/chain_client/37_GetTx.py b/examples/chain_client/tx/query/1_GetTx.py similarity index 100% rename from examples/chain_client/37_GetTx.py rename to examples/chain_client/tx/query/1_GetTx.py diff --git a/examples/chain_client/40_MsgExecuteContract.py b/examples/chain_client/wasm/1_MsgExecuteContract.py similarity index 88% rename from examples/chain_client/40_MsgExecuteContract.py rename to examples/chain_client/wasm/1_MsgExecuteContract.py index fef42954..d18c6398 100644 --- a/examples/chain_client/40_MsgExecuteContract.py +++ b/examples/chain_client/wasm/1_MsgExecuteContract.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -28,12 +33,12 @@ async def main() -> None: # prepare tx msg # NOTE: COIN MUST BE SORTED IN ALPHABETICAL ORDER BY DENOMS funds = [ - composer.Coin( + composer.coin( amount=69, denom="factory/inj1hdvy6tl89llqy3ze8lv6mz5qh66sx9enn0jxg6/inj12ngevx045zpvacus9s6anr258gkwpmthnz80e9", ), - composer.Coin(amount=420, denom="peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7"), - composer.Coin(amount=1, denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"), + composer.coin(amount=420, denom="peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7"), + composer.coin(amount=1, denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"), ] msg = composer.MsgExecuteContract( sender=address.to_acc_bech32(), @@ -66,7 +71,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/67_ContractsByCreator.py b/examples/chain_client/wasm/query/10_ContractsByCreator.py similarity index 100% rename from examples/chain_client/67_ContractsByCreator.py rename to examples/chain_client/wasm/query/10_ContractsByCreator.py diff --git a/examples/chain_client/58_ContractInfo.py b/examples/chain_client/wasm/query/1_ContractInfo.py similarity index 100% rename from examples/chain_client/58_ContractInfo.py rename to examples/chain_client/wasm/query/1_ContractInfo.py diff --git a/examples/chain_client/59_ContractHistory.py b/examples/chain_client/wasm/query/2_ContractHistory.py similarity index 100% rename from examples/chain_client/59_ContractHistory.py rename to examples/chain_client/wasm/query/2_ContractHistory.py diff --git a/examples/chain_client/60_ContractsByCode.py b/examples/chain_client/wasm/query/3_ContractsByCode.py similarity index 100% rename from examples/chain_client/60_ContractsByCode.py rename to examples/chain_client/wasm/query/3_ContractsByCode.py diff --git a/examples/chain_client/61_AllContractsState.py b/examples/chain_client/wasm/query/4_AllContractsState.py similarity index 100% rename from examples/chain_client/61_AllContractsState.py rename to examples/chain_client/wasm/query/4_AllContractsState.py diff --git a/examples/chain_client/62_RawContractState.py b/examples/chain_client/wasm/query/5_RawContractState.py similarity index 100% rename from examples/chain_client/62_RawContractState.py rename to examples/chain_client/wasm/query/5_RawContractState.py diff --git a/examples/chain_client/63_SmartContractState.py b/examples/chain_client/wasm/query/6_SmartContractState.py similarity index 100% rename from examples/chain_client/63_SmartContractState.py rename to examples/chain_client/wasm/query/6_SmartContractState.py diff --git a/examples/chain_client/64_SmartContractCode.py b/examples/chain_client/wasm/query/7_SmartContractCode.py similarity index 100% rename from examples/chain_client/64_SmartContractCode.py rename to examples/chain_client/wasm/query/7_SmartContractCode.py diff --git a/examples/chain_client/65_SmartContractCodes.py b/examples/chain_client/wasm/query/8_SmartContractCodes.py similarity index 100% rename from examples/chain_client/65_SmartContractCodes.py rename to examples/chain_client/wasm/query/8_SmartContractCodes.py diff --git a/examples/chain_client/66_SmartContractPinnedCodes.py b/examples/chain_client/wasm/query/9_SmartContractPinnedCodes.py similarity index 100% rename from examples/chain_client/66_SmartContractPinnedCodes.py rename to examples/chain_client/wasm/query/9_SmartContractPinnedCodes.py diff --git a/examples/chain_client/76_MsgExecuteContractCompat.py b/examples/chain_client/wasmx/1_MsgExecuteContractCompat.py similarity index 93% rename from examples/chain_client/76_MsgExecuteContractCompat.py rename to examples/chain_client/wasmx/1_MsgExecuteContractCompat.py index 978ff115..a195c7c4 100644 --- a/examples/chain_client/76_MsgExecuteContractCompat.py +++ b/examples/chain_client/wasmx/1_MsgExecuteContractCompat.py @@ -1,6 +1,8 @@ import asyncio import json +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + 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()) @@ -63,7 +68,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/poetry.lock b/poetry.lock index 9d754939..30d01a9d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -635,63 +635,63 @@ files = [ [[package]] name = "coverage" -version = "7.4.1" +version = "7.4.3" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:077d366e724f24fc02dbfe9d946534357fda71af9764ff99d73c3c596001bbd7"}, - {file = "coverage-7.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0193657651f5399d433c92f8ae264aff31fc1d066deee4b831549526433f3f61"}, - {file = "coverage-7.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d17bbc946f52ca67adf72a5ee783cd7cd3477f8f8796f59b4974a9b59cacc9ee"}, - {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3277f5fa7483c927fe3a7b017b39351610265308f5267ac6d4c2b64cc1d8d25"}, - {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dceb61d40cbfcf45f51e59933c784a50846dc03211054bd76b421a713dcdf19"}, - {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6008adeca04a445ea6ef31b2cbaf1d01d02986047606f7da266629afee982630"}, - {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c61f66d93d712f6e03369b6a7769233bfda880b12f417eefdd4f16d1deb2fc4c"}, - {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9bb62fac84d5f2ff523304e59e5c439955fb3b7f44e3d7b2085184db74d733b"}, - {file = "coverage-7.4.1-cp310-cp310-win32.whl", hash = "sha256:f86f368e1c7ce897bf2457b9eb61169a44e2ef797099fb5728482b8d69f3f016"}, - {file = "coverage-7.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:869b5046d41abfea3e381dd143407b0d29b8282a904a19cb908fa24d090cc018"}, - {file = "coverage-7.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8ffb498a83d7e0305968289441914154fb0ef5d8b3157df02a90c6695978295"}, - {file = "coverage-7.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3cacfaefe6089d477264001f90f55b7881ba615953414999c46cc9713ff93c8c"}, - {file = "coverage-7.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d6850e6e36e332d5511a48a251790ddc545e16e8beaf046c03985c69ccb2676"}, - {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18e961aa13b6d47f758cc5879383d27b5b3f3dcd9ce8cdbfdc2571fe86feb4dd"}, - {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfd1e1b9f0898817babf840b77ce9fe655ecbe8b1b327983df485b30df8cc011"}, - {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6b00e21f86598b6330f0019b40fb397e705135040dbedc2ca9a93c7441178e74"}, - {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:536d609c6963c50055bab766d9951b6c394759190d03311f3e9fcf194ca909e1"}, - {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7ac8f8eb153724f84885a1374999b7e45734bf93a87d8df1e7ce2146860edef6"}, - {file = "coverage-7.4.1-cp311-cp311-win32.whl", hash = "sha256:f3771b23bb3675a06f5d885c3630b1d01ea6cac9e84a01aaf5508706dba546c5"}, - {file = "coverage-7.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:9d2f9d4cc2a53b38cabc2d6d80f7f9b7e3da26b2f53d48f05876fef7956b6968"}, - {file = "coverage-7.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f68ef3660677e6624c8cace943e4765545f8191313a07288a53d3da188bd8581"}, - {file = "coverage-7.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23b27b8a698e749b61809fb637eb98ebf0e505710ec46a8aa6f1be7dc0dc43a6"}, - {file = "coverage-7.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e3424c554391dc9ef4a92ad28665756566a28fecf47308f91841f6c49288e66"}, - {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0860a348bf7004c812c8368d1fc7f77fe8e4c095d661a579196a9533778e156"}, - {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe558371c1bdf3b8fa03e097c523fb9645b8730399c14fe7721ee9c9e2a545d3"}, - {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3468cc8720402af37b6c6e7e2a9cdb9f6c16c728638a2ebc768ba1ef6f26c3a1"}, - {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:02f2edb575d62172aa28fe00efe821ae31f25dc3d589055b3fb64d51e52e4ab1"}, - {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ca6e61dc52f601d1d224526360cdeab0d0712ec104a2ce6cc5ccef6ed9a233bc"}, - {file = "coverage-7.4.1-cp312-cp312-win32.whl", hash = "sha256:ca7b26a5e456a843b9b6683eada193fc1f65c761b3a473941efe5a291f604c74"}, - {file = "coverage-7.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:85ccc5fa54c2ed64bd91ed3b4a627b9cce04646a659512a051fa82a92c04a448"}, - {file = "coverage-7.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8bdb0285a0202888d19ec6b6d23d5990410decb932b709f2b0dfe216d031d218"}, - {file = "coverage-7.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:918440dea04521f499721c039863ef95433314b1db00ff826a02580c1f503e45"}, - {file = "coverage-7.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:379d4c7abad5afbe9d88cc31ea8ca262296480a86af945b08214eb1a556a3e4d"}, - {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b094116f0b6155e36a304ff912f89bbb5067157aff5f94060ff20bbabdc8da06"}, - {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f5968608b1fe2a1d00d01ad1017ee27efd99b3437e08b83ded9b7af3f6f766"}, - {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:10e88e7f41e6197ea0429ae18f21ff521d4f4490aa33048f6c6f94c6045a6a75"}, - {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a4a3907011d39dbc3e37bdc5df0a8c93853c369039b59efa33a7b6669de04c60"}, - {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d224f0c4c9c98290a6990259073f496fcec1b5cc613eecbd22786d398ded3ad"}, - {file = "coverage-7.4.1-cp38-cp38-win32.whl", hash = "sha256:23f5881362dcb0e1a92b84b3c2809bdc90db892332daab81ad8f642d8ed55042"}, - {file = "coverage-7.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:a07f61fc452c43cd5328b392e52555f7d1952400a1ad09086c4a8addccbd138d"}, - {file = "coverage-7.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8e738a492b6221f8dcf281b67129510835461132b03024830ac0e554311a5c54"}, - {file = "coverage-7.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46342fed0fff72efcda77040b14728049200cbba1279e0bf1188f1f2078c1d70"}, - {file = "coverage-7.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9641e21670c68c7e57d2053ddf6c443e4f0a6e18e547e86af3fad0795414a628"}, - {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aeb2c2688ed93b027eb0d26aa188ada34acb22dceea256d76390eea135083950"}, - {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d12c923757de24e4e2110cf8832d83a886a4cf215c6e61ed506006872b43a6d1"}, - {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0491275c3b9971cdbd28a4595c2cb5838f08036bca31765bad5e17edf900b2c7"}, - {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8dfc5e195bbef80aabd81596ef52a1277ee7143fe419efc3c4d8ba2754671756"}, - {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a78b656a4d12b0490ca72651fe4d9f5e07e3c6461063a9b6265ee45eb2bdd35"}, - {file = "coverage-7.4.1-cp39-cp39-win32.whl", hash = "sha256:f90515974b39f4dea2f27c0959688621b46d96d5a626cf9c53dbc653a895c05c"}, - {file = "coverage-7.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:64e723ca82a84053dd7bfcc986bdb34af8d9da83c521c19d6b472bc6880e191a"}, - {file = "coverage-7.4.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:32a8d985462e37cfdab611a6f95b09d7c091d07668fdc26e47a725ee575fe166"}, - {file = "coverage-7.4.1.tar.gz", hash = "sha256:1ed4b95480952b1a26d863e546fa5094564aa0065e1e5f0d4d0041f293251d04"}, + {file = "coverage-7.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8580b827d4746d47294c0e0b92854c85a92c2227927433998f0d3320ae8a71b6"}, + {file = "coverage-7.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:718187eeb9849fc6cc23e0d9b092bc2348821c5e1a901c9f8975df0bc785bfd4"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:767b35c3a246bcb55b8044fd3a43b8cd553dd1f9f2c1eeb87a302b1f8daa0524"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae7f19afe0cce50039e2c782bff379c7e347cba335429678450b8fe81c4ef96d"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba3a8aaed13770e970b3df46980cb068d1c24af1a1968b7818b69af8c4347efb"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ee866acc0861caebb4f2ab79f0b94dbfbdbfadc19f82e6e9c93930f74e11d7a0"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:506edb1dd49e13a2d4cac6a5173317b82a23c9d6e8df63efb4f0380de0fbccbc"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd6545d97c98a192c5ac995d21c894b581f1fd14cf389be90724d21808b657e2"}, + {file = "coverage-7.4.3-cp310-cp310-win32.whl", hash = "sha256:f6a09b360d67e589236a44f0c39218a8efba2593b6abdccc300a8862cffc2f94"}, + {file = "coverage-7.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:18d90523ce7553dd0b7e23cbb28865db23cddfd683a38fb224115f7826de78d0"}, + {file = "coverage-7.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbbe5e739d45a52f3200a771c6d2c7acf89eb2524890a4a3aa1a7fa0695d2a47"}, + {file = "coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:489763b2d037b164846ebac0cbd368b8a4ca56385c4090807ff9fad817de4113"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451f433ad901b3bb00184d83fd83d135fb682d780b38af7944c9faeecb1e0bfe"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc66e222cf4c719fe7722a403888b1f5e1682d1679bd780e2b26c18bb648cdc"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ec74cfef2d985e145baae90d9b1b32f85e1741b04cd967aaf9cfa84c1334f3"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:abbbd8093c5229c72d4c2926afaee0e6e3140de69d5dcd918b2921f2f0c8baba"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:35eb581efdacf7b7422af677b92170da4ef34500467381e805944a3201df2079"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8249b1c7334be8f8c3abcaaa996e1e4927b0e5a23b65f5bf6cfe3180d8ca7840"}, + {file = "coverage-7.4.3-cp311-cp311-win32.whl", hash = "sha256:cf30900aa1ba595312ae41978b95e256e419d8a823af79ce670835409fc02ad3"}, + {file = "coverage-7.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:18c7320695c949de11a351742ee001849912fd57e62a706d83dfc1581897fa2e"}, + {file = "coverage-7.4.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b51bfc348925e92a9bd9b2e48dad13431b57011fd1038f08316e6bf1df107d10"}, + {file = "coverage-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6cdecaedea1ea9e033d8adf6a0ab11107b49571bbb9737175444cea6eb72328"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2eccb883368f9e972e216c7b4c7c06cabda925b5f06dde0650281cb7666a30"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c00cdc8fa4e50e1cc1f941a7f2e3e0f26cb2a1233c9696f26963ff58445bac7"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4a8dd3dcf4cbd3165737358e4d7dfbd9d59902ad11e3b15eebb6393b0446e"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:062b0a75d9261e2f9c6d071753f7eef0fc9caf3a2c82d36d76667ba7b6470003"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ebe7c9e67a2d15fa97b77ea6571ce5e1e1f6b0db71d1d5e96f8d2bf134303c1d"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0a120238dd71c68484f02562f6d446d736adcc6ca0993712289b102705a9a3a"}, + {file = "coverage-7.4.3-cp312-cp312-win32.whl", hash = "sha256:37389611ba54fd6d278fde86eb2c013c8e50232e38f5c68235d09d0a3f8aa352"}, + {file = "coverage-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:d25b937a5d9ffa857d41be042b4238dd61db888533b53bc76dc082cb5a15e914"}, + {file = "coverage-7.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:28ca2098939eabab044ad68850aac8f8db6bf0b29bc7f2887d05889b17346454"}, + {file = "coverage-7.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:280459f0a03cecbe8800786cdc23067a8fc64c0bd51dc614008d9c36e1659d7e"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c0cdedd3500e0511eac1517bf560149764b7d8e65cb800d8bf1c63ebf39edd2"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a9babb9466fe1da12417a4aed923e90124a534736de6201794a3aea9d98484e"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dec9de46a33cf2dd87a5254af095a409ea3bf952d85ad339751e7de6d962cde6"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:16bae383a9cc5abab9bb05c10a3e5a52e0a788325dc9ba8499e821885928968c"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2c854ce44e1ee31bda4e318af1dbcfc929026d12c5ed030095ad98197eeeaed0"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ce8c50520f57ec57aa21a63ea4f325c7b657386b3f02ccaedeccf9ebe27686e1"}, + {file = "coverage-7.4.3-cp38-cp38-win32.whl", hash = "sha256:708a3369dcf055c00ddeeaa2b20f0dd1ce664eeabde6623e516c5228b753654f"}, + {file = "coverage-7.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:1bf25fbca0c8d121a3e92a2a0555c7e5bc981aee5c3fdaf4bb7809f410f696b9"}, + {file = "coverage-7.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b253094dbe1b431d3a4ac2f053b6d7ede2664ac559705a704f621742e034f1f"}, + {file = "coverage-7.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77fbfc5720cceac9c200054b9fab50cb2a7d79660609200ab83f5db96162d20c"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6679060424faa9c11808598504c3ab472de4531c571ab2befa32f4971835788e"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4af154d617c875b52651dd8dd17a31270c495082f3d55f6128e7629658d63765"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8640f1fde5e1b8e3439fe482cdc2b0bb6c329f4bb161927c28d2e8879c6029ee"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:69b9f6f66c0af29642e73a520b6fed25ff9fd69a25975ebe6acb297234eda501"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0842571634f39016a6c03e9d4aba502be652a6e4455fadb73cd3a3a49173e38f"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a78ed23b08e8ab524551f52953a8a05d61c3a760781762aac49f8de6eede8c45"}, + {file = "coverage-7.4.3-cp39-cp39-win32.whl", hash = "sha256:c0524de3ff096e15fcbfe8f056fdb4ea0bf497d584454f344d59fce069d3e6e9"}, + {file = "coverage-7.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:0209a6369ccce576b43bb227dc8322d8ef9e323d089c6f3f26a597b09cb4d2aa"}, + {file = "coverage-7.4.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:7cbde573904625509a3f37b6fecea974e363460b556a627c60dc2f47e2fffa51"}, + {file = "coverage-7.4.3.tar.gz", hash = "sha256:276f6077a5c61447a48d133ed13e759c09e62aff0dc84274a68dc18660104d52"}, ] [package.dependencies] @@ -899,13 +899,13 @@ files = [ [[package]] name = "eth-abi" -version = "5.0.0" +version = "5.0.1" description = "eth_abi: Python utilities for working with Ethereum ABI definitions, especially encoding and decoding" optional = false python-versions = ">=3.8, <4" files = [ - {file = "eth_abi-5.0.0-py3-none-any.whl", hash = "sha256:936a715d7366ac13cac665cbdaf01cc4aabbe8c2d810d716287a9634f9665e01"}, - {file = "eth_abi-5.0.0.tar.gz", hash = "sha256:89c4454d794d9ed92ad5cb2794698c5cee6b7b3ca6009187d0e282adc7f9b6dc"}, + {file = "eth_abi-5.0.1-py3-none-any.whl", hash = "sha256:521960d8b4beee514958e1774951dc6b48176aa274e3bd8b166f6921453047ef"}, + {file = "eth_abi-5.0.1.tar.gz", hash = "sha256:e9425110c6120c585c9f0db2e8a33d76c4b886b148a65e68fc0035d3917a3b9c"}, ] [package.dependencies] @@ -914,9 +914,9 @@ eth-utils = ">=2.0.0" parsimonious = ">=0.9.0,<0.10.0" [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -test = ["eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-xdist (>=2.4.0)"] +test = ["eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.0.0)", "pytest-xdist (>=2.4.0)"] tools = ["hypothesis (>=4.18.2,<5.0.0)"] [[package]] @@ -948,13 +948,13 @@ test = ["coverage", "hypothesis (>=4.18.0,<5)", "pytest (>=7.0.0)", "pytest-xdis [[package]] name = "eth-hash" -version = "0.6.0" +version = "0.7.0" description = "eth-hash: The Ethereum hashing function, keccak256, sometimes (erroneously) called sha3" optional = false python-versions = ">=3.8, <4" files = [ - {file = "eth-hash-0.6.0.tar.gz", hash = "sha256:ae72889e60db6acbb3872c288cfa02ed157f4c27630fcd7f9c8442302c31e478"}, - {file = "eth_hash-0.6.0-py3-none-any.whl", hash = "sha256:9f8daaa345764f8871dc461855049ac54ae4291d780279bce6fce7f24e3f17d3"}, + {file = "eth-hash-0.7.0.tar.gz", hash = "sha256:bacdc705bfd85dadd055ecd35fd1b4f846b671add101427e089a4ca2e8db310a"}, + {file = "eth_hash-0.7.0-py3-none-any.whl", hash = "sha256:b8d5a230a2b251f4a291e3164a23a14057c4a6de4b0aa4a16fa4dc9161b57e2f"}, ] [package.dependencies] @@ -969,13 +969,13 @@ test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-keyfile" -version = "0.7.0" +version = "0.8.0" description = "eth-keyfile: A library for handling the encrypted keyfiles used to store ethereum private keys" optional = false python-versions = ">=3.8, <4" files = [ - {file = "eth-keyfile-0.7.0.tar.gz", hash = "sha256:6bdb8110c3a50439deb68a04c93c9d5ddd5402353bfae1bf4cfca1d6dff14fcf"}, - {file = "eth_keyfile-0.7.0-py3-none-any.whl", hash = "sha256:6a89b231a2fe250c3a8f924f2695bb9cce33ddd0d6f7ebbcdacd183d7f83d537"}, + {file = "eth-keyfile-0.8.0.tar.gz", hash = "sha256:02e3c2e564c7403b92db3fef8ecae3d21123b15787daecd5b643a57369c530f9"}, + {file = "eth_keyfile-0.8.0-py3-none-any.whl", hash = "sha256:9e09f5bc97c8309876c06bdea7a94f0051c25ba3109b5df37afb815418322efe"}, ] [package.dependencies] @@ -1230,135 +1230,135 @@ files = [ [[package]] name = "grpcio" -version = "1.60.1" +version = "1.62.0" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.7" files = [ - {file = "grpcio-1.60.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:14e8f2c84c0832773fb3958240c69def72357bc11392571f87b2d7b91e0bb092"}, - {file = "grpcio-1.60.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:33aed0a431f5befeffd9d346b0fa44b2c01aa4aeae5ea5b2c03d3e25e0071216"}, - {file = "grpcio-1.60.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:fead980fbc68512dfd4e0c7b1f5754c2a8e5015a04dea454b9cada54a8423525"}, - {file = "grpcio-1.60.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:082081e6a36b6eb5cf0fd9a897fe777dbb3802176ffd08e3ec6567edd85bc104"}, - {file = "grpcio-1.60.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55ccb7db5a665079d68b5c7c86359ebd5ebf31a19bc1a91c982fd622f1e31ff2"}, - {file = "grpcio-1.60.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9b54577032d4f235452f77a83169b6527bf4b77d73aeada97d45b2aaf1bf5ce0"}, - {file = "grpcio-1.60.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7d142bcd604166417929b071cd396aa13c565749a4c840d6c702727a59d835eb"}, - {file = "grpcio-1.60.1-cp310-cp310-win32.whl", hash = "sha256:2a6087f234cb570008a6041c8ffd1b7d657b397fdd6d26e83d72283dae3527b1"}, - {file = "grpcio-1.60.1-cp310-cp310-win_amd64.whl", hash = "sha256:f2212796593ad1d0235068c79836861f2201fc7137a99aa2fea7beeb3b101177"}, - {file = "grpcio-1.60.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:79ae0dc785504cb1e1788758c588c711f4e4a0195d70dff53db203c95a0bd303"}, - {file = "grpcio-1.60.1-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:4eec8b8c1c2c9b7125508ff7c89d5701bf933c99d3910e446ed531cd16ad5d87"}, - {file = "grpcio-1.60.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:8c9554ca8e26241dabe7951aa1fa03a1ba0856688ecd7e7bdbdd286ebc272e4c"}, - {file = "grpcio-1.60.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91422ba785a8e7a18725b1dc40fbd88f08a5bb4c7f1b3e8739cab24b04fa8a03"}, - {file = "grpcio-1.60.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cba6209c96828711cb7c8fcb45ecef8c8859238baf15119daa1bef0f6c84bfe7"}, - {file = "grpcio-1.60.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c71be3f86d67d8d1311c6076a4ba3b75ba5703c0b856b4e691c9097f9b1e8bd2"}, - {file = "grpcio-1.60.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:af5ef6cfaf0d023c00002ba25d0751e5995fa0e4c9eec6cd263c30352662cbce"}, - {file = "grpcio-1.60.1-cp311-cp311-win32.whl", hash = "sha256:a09506eb48fa5493c58f946c46754ef22f3ec0df64f2b5149373ff31fb67f3dd"}, - {file = "grpcio-1.60.1-cp311-cp311-win_amd64.whl", hash = "sha256:49c9b6a510e3ed8df5f6f4f3c34d7fbf2d2cae048ee90a45cd7415abab72912c"}, - {file = "grpcio-1.60.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:b58b855d0071575ea9c7bc0d84a06d2edfbfccec52e9657864386381a7ce1ae9"}, - {file = "grpcio-1.60.1-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:a731ac5cffc34dac62053e0da90f0c0b8560396a19f69d9703e88240c8f05858"}, - {file = "grpcio-1.60.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:cf77f8cf2a651fbd869fbdcb4a1931464189cd210abc4cfad357f1cacc8642a6"}, - {file = "grpcio-1.60.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c557e94e91a983e5b1e9c60076a8fd79fea1e7e06848eb2e48d0ccfb30f6e073"}, - {file = "grpcio-1.60.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:069fe2aeee02dfd2135d562d0663fe70fbb69d5eed6eb3389042a7e963b54de8"}, - {file = "grpcio-1.60.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cb0af13433dbbd1c806e671d81ec75bd324af6ef75171fd7815ca3074fe32bfe"}, - {file = "grpcio-1.60.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2f44c32aef186bbba254129cea1df08a20be414144ac3bdf0e84b24e3f3b2e05"}, - {file = "grpcio-1.60.1-cp312-cp312-win32.whl", hash = "sha256:a212e5dea1a4182e40cd3e4067ee46be9d10418092ce3627475e995cca95de21"}, - {file = "grpcio-1.60.1-cp312-cp312-win_amd64.whl", hash = "sha256:6e490fa5f7f5326222cb9f0b78f207a2b218a14edf39602e083d5f617354306f"}, - {file = "grpcio-1.60.1-cp37-cp37m-linux_armv7l.whl", hash = "sha256:4216e67ad9a4769117433814956031cb300f85edc855252a645a9a724b3b6594"}, - {file = "grpcio-1.60.1-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:73e14acd3d4247169955fae8fb103a2b900cfad21d0c35f0dcd0fdd54cd60367"}, - {file = "grpcio-1.60.1-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:6ecf21d20d02d1733e9c820fb5c114c749d888704a7ec824b545c12e78734d1c"}, - {file = "grpcio-1.60.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33bdea30dcfd4f87b045d404388469eb48a48c33a6195a043d116ed1b9a0196c"}, - {file = "grpcio-1.60.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53b69e79d00f78c81eecfb38f4516080dc7f36a198b6b37b928f1c13b3c063e9"}, - {file = "grpcio-1.60.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:39aa848794b887120b1d35b1b994e445cc028ff602ef267f87c38122c1add50d"}, - {file = "grpcio-1.60.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:72153a0d2e425f45b884540a61c6639436ddafa1829a42056aa5764b84108b8e"}, - {file = "grpcio-1.60.1-cp37-cp37m-win_amd64.whl", hash = "sha256:50d56280b482875d1f9128ce596e59031a226a8b84bec88cb2bf76c289f5d0de"}, - {file = "grpcio-1.60.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:6d140bdeb26cad8b93c1455fa00573c05592793c32053d6e0016ce05ba267549"}, - {file = "grpcio-1.60.1-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:bc808924470643b82b14fe121923c30ec211d8c693e747eba8a7414bc4351a23"}, - {file = "grpcio-1.60.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:70c83bb530572917be20c21f3b6be92cd86b9aecb44b0c18b1d3b2cc3ae47df0"}, - {file = "grpcio-1.60.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9b106bc52e7f28170e624ba61cc7dc6829566e535a6ec68528f8e1afbed1c41f"}, - {file = "grpcio-1.60.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30e980cd6db1088c144b92fe376747328d5554bc7960ce583ec7b7d81cd47287"}, - {file = "grpcio-1.60.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0c5807e9152eff15f1d48f6b9ad3749196f79a4a050469d99eecb679be592acc"}, - {file = "grpcio-1.60.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f1c3dc536b3ee124e8b24feb7533e5c70b9f2ef833e3b2e5513b2897fd46763a"}, - {file = "grpcio-1.60.1-cp38-cp38-win32.whl", hash = "sha256:d7404cebcdb11bb5bd40bf94131faf7e9a7c10a6c60358580fe83913f360f929"}, - {file = "grpcio-1.60.1-cp38-cp38-win_amd64.whl", hash = "sha256:c8754c75f55781515a3005063d9a05878b2cfb3cb7e41d5401ad0cf19de14872"}, - {file = "grpcio-1.60.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:0250a7a70b14000fa311de04b169cc7480be6c1a769b190769d347939d3232a8"}, - {file = "grpcio-1.60.1-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:660fc6b9c2a9ea3bb2a7e64ba878c98339abaf1811edca904ac85e9e662f1d73"}, - {file = "grpcio-1.60.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:76eaaba891083fcbe167aa0f03363311a9f12da975b025d30e94b93ac7a765fc"}, - {file = "grpcio-1.60.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d97c65ea7e097056f3d1ead77040ebc236feaf7f71489383d20f3b4c28412a"}, - {file = "grpcio-1.60.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb2a2911b028f01c8c64d126f6b632fcd8a9ac975aa1b3855766c94e4107180"}, - {file = "grpcio-1.60.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:5a1ebbae7e2214f51b1f23b57bf98eeed2cf1ba84e4d523c48c36d5b2f8829ff"}, - {file = "grpcio-1.60.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a66f4d2a005bc78e61d805ed95dedfcb35efa84b7bba0403c6d60d13a3de2d6"}, - {file = "grpcio-1.60.1-cp39-cp39-win32.whl", hash = "sha256:8d488fbdbf04283f0d20742b64968d44825617aa6717b07c006168ed16488804"}, - {file = "grpcio-1.60.1-cp39-cp39-win_amd64.whl", hash = "sha256:61b7199cd2a55e62e45bfb629a35b71fc2c0cb88f686a047f25b1112d3810904"}, - {file = "grpcio-1.60.1.tar.gz", hash = "sha256:dd1d3a8d1d2e50ad9b59e10aa7f07c7d1be2b367f3f2d33c5fade96ed5460962"}, + {file = "grpcio-1.62.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:136ffd79791b1eddda8d827b607a6285474ff8a1a5735c4947b58c481e5e4271"}, + {file = "grpcio-1.62.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:d6a56ba703be6b6267bf19423d888600c3f574ac7c2cc5e6220af90662a4d6b0"}, + {file = "grpcio-1.62.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:4cd356211579043fce9f52acc861e519316fff93980a212c8109cca8f47366b6"}, + {file = "grpcio-1.62.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e803e9b58d8f9b4ff0ea991611a8d51b31c68d2e24572cd1fe85e99e8cc1b4f8"}, + {file = "grpcio-1.62.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4c04fe33039b35b97c02d2901a164bbbb2f21fb9c4e2a45a959f0b044c3512c"}, + {file = "grpcio-1.62.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:95370c71b8c9062f9ea033a0867c4c73d6f0ff35113ebd2618171ec1f1e903e0"}, + {file = "grpcio-1.62.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c912688acc05e4ff012c8891803659d6a8a8b5106f0f66e0aed3fb7e77898fa6"}, + {file = "grpcio-1.62.0-cp310-cp310-win32.whl", hash = "sha256:821a44bd63d0f04e33cf4ddf33c14cae176346486b0df08b41a6132b976de5fc"}, + {file = "grpcio-1.62.0-cp310-cp310-win_amd64.whl", hash = "sha256:81531632f93fece32b2762247c4c169021177e58e725494f9a746ca62c83acaa"}, + {file = "grpcio-1.62.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:3fa15850a6aba230eed06b236287c50d65a98f05054a0f01ccedf8e1cc89d57f"}, + {file = "grpcio-1.62.0-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:36df33080cd7897623feff57831eb83c98b84640b016ce443305977fac7566fb"}, + {file = "grpcio-1.62.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:7a195531828b46ea9c4623c47e1dc45650fc7206f8a71825898dd4c9004b0928"}, + {file = "grpcio-1.62.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab140a3542bbcea37162bdfc12ce0d47a3cda3f2d91b752a124cc9fe6776a9e2"}, + {file = "grpcio-1.62.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f9d6c3223914abb51ac564dc9c3782d23ca445d2864321b9059d62d47144021"}, + {file = "grpcio-1.62.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fbe0c20ce9a1cff75cfb828b21f08d0a1ca527b67f2443174af6626798a754a4"}, + {file = "grpcio-1.62.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:38f69de9c28c1e7a8fd24e4af4264726637b72f27c2099eaea6e513e7142b47e"}, + {file = "grpcio-1.62.0-cp311-cp311-win32.whl", hash = "sha256:ce1aafdf8d3f58cb67664f42a617af0e34555fe955450d42c19e4a6ad41c84bd"}, + {file = "grpcio-1.62.0-cp311-cp311-win_amd64.whl", hash = "sha256:eef1d16ac26c5325e7d39f5452ea98d6988c700c427c52cbc7ce3201e6d93334"}, + {file = "grpcio-1.62.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8aab8f90b2a41208c0a071ec39a6e5dbba16fd827455aaa070fec241624ccef8"}, + {file = "grpcio-1.62.0-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:62aa1659d8b6aad7329ede5d5b077e3d71bf488d85795db517118c390358d5f6"}, + {file = "grpcio-1.62.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:0d7ae7fc7dbbf2d78d6323641ded767d9ec6d121aaf931ec4a5c50797b886532"}, + {file = "grpcio-1.62.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f359d635ee9428f0294bea062bb60c478a8ddc44b0b6f8e1f42997e5dc12e2ee"}, + {file = "grpcio-1.62.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d48e5b1f8f4204889f1acf30bb57c30378e17c8d20df5acbe8029e985f735c"}, + {file = "grpcio-1.62.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:662d3df5314ecde3184cf87ddd2c3a66095b3acbb2d57a8cada571747af03873"}, + {file = "grpcio-1.62.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:92cdb616be44c8ac23a57cce0243af0137a10aa82234f23cd46e69e115071388"}, + {file = "grpcio-1.62.0-cp312-cp312-win32.whl", hash = "sha256:0b9179478b09ee22f4a36b40ca87ad43376acdccc816ce7c2193a9061bf35701"}, + {file = "grpcio-1.62.0-cp312-cp312-win_amd64.whl", hash = "sha256:614c3ed234208e76991992342bab725f379cc81c7dd5035ee1de2f7e3f7a9842"}, + {file = "grpcio-1.62.0-cp37-cp37m-linux_armv7l.whl", hash = "sha256:7e1f51e2a460b7394670fdb615e26d31d3260015154ea4f1501a45047abe06c9"}, + {file = "grpcio-1.62.0-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:bcff647e7fe25495e7719f779cc219bbb90b9e79fbd1ce5bda6aae2567f469f2"}, + {file = "grpcio-1.62.0-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:56ca7ba0b51ed0de1646f1735154143dcbdf9ec2dbe8cc6645def299bb527ca1"}, + {file = "grpcio-1.62.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e84bfb2a734e4a234b116be208d6f0214e68dcf7804306f97962f93c22a1839"}, + {file = "grpcio-1.62.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c1488b31a521fbba50ae86423f5306668d6f3a46d124f7819c603979fc538c4"}, + {file = "grpcio-1.62.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:98d8f4eb91f1ce0735bf0b67c3b2a4fea68b52b2fd13dc4318583181f9219b4b"}, + {file = "grpcio-1.62.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b3d3d755cfa331d6090e13aac276d4a3fb828bf935449dc16c3d554bf366136b"}, + {file = "grpcio-1.62.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a33f2bfd8a58a02aab93f94f6c61279be0f48f99fcca20ebaee67576cd57307b"}, + {file = "grpcio-1.62.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:5e709f7c8028ce0443bddc290fb9c967c1e0e9159ef7a030e8c21cac1feabd35"}, + {file = "grpcio-1.62.0-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:2f3d9a4d0abb57e5f49ed5039d3ed375826c2635751ab89dcc25932ff683bbb6"}, + {file = "grpcio-1.62.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:62ccb92f594d3d9fcd00064b149a0187c246b11e46ff1b7935191f169227f04c"}, + {file = "grpcio-1.62.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:921148f57c2e4b076af59a815467d399b7447f6e0ee10ef6d2601eb1e9c7f402"}, + {file = "grpcio-1.62.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f897b16190b46bc4d4aaf0a32a4b819d559a37a756d7c6b571e9562c360eed72"}, + {file = "grpcio-1.62.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1bc8449084fe395575ed24809752e1dc4592bb70900a03ca42bf236ed5bf008f"}, + {file = "grpcio-1.62.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81d444e5e182be4c7856cd33a610154fe9ea1726bd071d07e7ba13fafd202e38"}, + {file = "grpcio-1.62.0-cp38-cp38-win32.whl", hash = "sha256:88f41f33da3840b4a9bbec68079096d4caf629e2c6ed3a72112159d570d98ebe"}, + {file = "grpcio-1.62.0-cp38-cp38-win_amd64.whl", hash = "sha256:fc2836cb829895ee190813446dce63df67e6ed7b9bf76060262c55fcd097d270"}, + {file = "grpcio-1.62.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:fcc98cff4084467839d0a20d16abc2a76005f3d1b38062464d088c07f500d170"}, + {file = "grpcio-1.62.0-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:0d3dee701e48ee76b7d6fbbba18ba8bc142e5b231ef7d3d97065204702224e0e"}, + {file = "grpcio-1.62.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:b7a6be562dd18e5d5bec146ae9537f20ae1253beb971c0164f1e8a2f5a27e829"}, + {file = "grpcio-1.62.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29cb592c4ce64a023712875368bcae13938c7f03e99f080407e20ffe0a9aa33b"}, + {file = "grpcio-1.62.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eda79574aec8ec4d00768dcb07daba60ed08ef32583b62b90bbf274b3c279f7"}, + {file = "grpcio-1.62.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7eea57444a354ee217fda23f4b479a4cdfea35fb918ca0d8a0e73c271e52c09c"}, + {file = "grpcio-1.62.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0e97f37a3b7c89f9125b92d22e9c8323f4e76e7993ba7049b9f4ccbe8bae958a"}, + {file = "grpcio-1.62.0-cp39-cp39-win32.whl", hash = "sha256:39cd45bd82a2e510e591ca2ddbe22352e8413378852ae814549c162cf3992a93"}, + {file = "grpcio-1.62.0-cp39-cp39-win_amd64.whl", hash = "sha256:b71c65427bf0ec6a8b48c68c17356cb9fbfc96b1130d20a07cb462f4e4dcdcd5"}, + {file = "grpcio-1.62.0.tar.gz", hash = "sha256:748496af9238ac78dcd98cce65421f1adce28c3979393e3609683fcd7f3880d7"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.60.1)"] +protobuf = ["grpcio-tools (>=1.62.0)"] [[package]] name = "grpcio-tools" -version = "1.60.1" +version = "1.62.0" description = "Protobuf code generator for gRPC" optional = false python-versions = ">=3.7" files = [ - {file = "grpcio-tools-1.60.1.tar.gz", hash = "sha256:da08224ab8675c6d464b988bd8ca02cccd2bf0275bceefe8f6219bfd4a4f5e85"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:184b27333b627a7cc0972fb70d21a8bb7c02ac4a6febc16768d78ea8ff883ddd"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:18d7737f29ef5bbe3352547d0eccd080807834f00df223867dfc860bf81e9180"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:cc8ba358d2c658c6ecbc58e779bf0fc5a673fecac015a70db27fc5b4d37b76b6"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2973f75e8ba5c551033a1d59cc97654f6f386deaf2559082011d245d7ed87bba"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28ae665113affebdd109247386786e5ab4dccfcfad1b5f68e9cce2e326b57ee6"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5c7ed086fef5ff59f46d53a052b1934b73e0f7d12365d656d6af3a88057d5a3e"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8540f6480428a52614db71dd6394f52cbc0d2565b5ea1136a982f26390a42c7a"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-win32.whl", hash = "sha256:5b4a939097005531edec331f22d0b82bff26e71ede009354d2f375b5d41e74f0"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-win_amd64.whl", hash = "sha256:075bb67895970f96aabc1761ca674bf4db193f8fcad387f08e50402023b5f953"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:284749d20fb22418f17d3d351b9eb838caf4a0393a9cb02c36e5c32fa4bbe9db"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:b1041377cf32ee2338284ee26e6b9c10f9ea7728092376b19803dcb9b91d510d"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:e529cd3d4109a6f4a3f7bdaca68946eb33734e2d7ffe861785a0586abe99ee67"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31294b534f25f02ead204e58dcbe0e5437a95a1a6f276bb9378905595b02ff6d"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fb6f4d2df0388c35c2804ba170f511238a681b679ead013bfe5e39d0ea9cf48"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:40cd8268a675269ce59c4fa50877597ec638bb1099c52237bb726c8ac9791868"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:985ac476da365267a2367ab20060f9096fbfc2e190fb02dd394f9ec05edf03ca"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-win32.whl", hash = "sha256:bd85f6c368b93ae45edf8568473053cb1cc075ef3489efb18f9832d4ecce062f"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-win_amd64.whl", hash = "sha256:c20e752ff5057758845f4e5c7a298739bfba291f373ed18ea9c7c7acbe69e8ab"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:aafc94616c5f89c891d859057b194a153c451f9921053454e9d7d4cbf79047eb"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:9bba347000f57dae8aea79c0d76ef7d72895597524d30d0170c7d1974a3a03f3"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:1e96a532d38411f0543fe1903ff522f7142a9901afb0ed94de58d79caf1905be"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ea6e397d87f458bb2c387a4a6e1b65df74ce5b5194a1f16850c38309012e981"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aeecd5b8faa2aab67e6c8b8a57e888c00ce70d39f331ede0a21312e92def1a6"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:d2c26ce5f774c98bd2d3d8d1703048394018b55d297ebdb41ed2ba35b9a34f68"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:214281cdafb7acfdcde848eca2de7c888a6e2b5cd25ab579712b965ea09a9cd4"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-win32.whl", hash = "sha256:8c4b917aa4fcdc77990773063f0f14540aab8d4a8bf6c862b964a45d891a31d2"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-win_amd64.whl", hash = "sha256:0aa34c7c21cff2177a4096b2b0d51dfbc9f8a41f929847a434e89b352c5a215d"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-linux_armv7l.whl", hash = "sha256:acdba77584981fe799104aa545d9d97910bcf88c69b668b768c1f3e7d7e5afac"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:2a7fa55bc62d4b8ebe6fb26f8cf89df3cf3b504eb6c5f3a2f0174689d35fddb0"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:dffa326cf901fe08a0e218d9fdf593f12276088a8caa07fcbec7d051149cf9ef"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf945bd22f396c0d0c691e0990db2bfc4e77816b1edc2aea8a69c35ae721aac9"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6801cfc5a85f0fb6fd12cade45942aaa1c814422328d594d12d364815fe34123"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f95bdc6c7c50b7fc442e53537bc5b4eb8cab2a671c1da80d40b5a4ab1fd5d416"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:402efeec36d8b12b792bae8a900085416fc2f57a34b599445ace2e847b6b0d75"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-win_amd64.whl", hash = "sha256:af88a2062b9c35034a80b25f289034b9c3c00c42bb88efaa465503a06fbd6a87"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:46b495bae31c5d3f6ac0240eb848f0642b5410f80dff2aacdea20cdea3938c1d"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:b5ae375207af9aa82f516dcd513d2e0c83690b7788d45844daad846ed87550f8"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:15f13e8f3d77b96adcb1e3615acec5b100bd836c6010c58a51465bcb9c06d128"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c354505e6a3d170da374f20404ea6a78135502df4f5534e5c532bdf24c4cc2a5"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8cfab27ba2bd36a3e3b522aed686133531e8b919703d0247a0885dae8815317"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b6ef213cb0aecb2832ee82a2eac32f29f31f50b17ce020604d82205096a6bd0c"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b62cb2d43a7f0eacc6a6962dfff7c2564874012e1a72ae4167e762f449e2912"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-win32.whl", hash = "sha256:3fcabf484720a9fa1690e2825fc940027a05a0c79a1075a730008ef634bd8ad2"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-win_amd64.whl", hash = "sha256:22ce3e3d861321d208d8bfd6161ab976623520b179712c90b2c175151463a6b1"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:4e66fe204da15e08e599adb3060109a42927c0868fe8933e2d341ea649eceb03"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:c1047bd831de5d9da761e9dc246988d5f07d722186938dfd5f34807398101010"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:eba5fafd70585fbd4cb6ae45e3c5e11d8598e2426c9f289b78f682c0606e81cb"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bba7230c60238c7a4ffa29f1aff6d78edb41f2c79cbe4443406472b1c80ccb5d"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2bb8efc2cd64bd8f2779b426dd7e94e60924078ba5150cbbb60a846e62d1ed2"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:26f91161a91f1601777751230eaaafdf416fed08a15c3ba2ae391088e4a906c6"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2c19be2bba5583e30f88bb5d71b430176c396f0d6d0db3785e5845bfa3d28cd2"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-win32.whl", hash = "sha256:9aadc9c00baa2064baa4414cff7c269455449f14805a355226674d89c507342c"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-win_amd64.whl", hash = "sha256:652b08c9fef39186ce4f97f05f5440c0ed41f117db0f7d6cb0e0d75dbc6afd3f"}, + {file = "grpcio-tools-1.62.0.tar.gz", hash = "sha256:7fca6ecfbbf0549058bb29dcc6e435d885b878d07701e77ac58e1e1f591736dc"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:465c51ebaa184ee3bb619cd5bfaf562bbdde166f2822a6935461e6a741f5ac19"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:0d9c9a4832f52c4597d6dc12d9ab3109c3bd0ee1686b8bf6d64f9eab4145e3cb"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:5a482d9625209023481e631c29a6df1392bfc49f9accfa880dabbacff642559a"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74196beed18383d53ff3e2412a6c1eefa3ff109e987be240368496bc3dcabc8b"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75aca28cbeb605c59b5689a7e000fbc2bd659d2f322c58461f3912f00069f6da"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:523adf731fa4c5af0bf7ee2edb65e8c7ef4d9df9951461d6a18fe096688efd2d"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:791aa220f8f1936e65bc079e9eb954fa0202a1f16e28b83956e59d17dface127"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-win32.whl", hash = "sha256:5dacc691b18d2c294ea971720ff980a1e2d68a3f7ddcd2f0670b3204e81c4b18"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-win_amd64.whl", hash = "sha256:6999a4e705b03aacad46e625feb7610e47ec88dbd51220c2282b6334f90721fc"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:19b74e141937c885c9e56b6a7dfa190ca7d583bd48bce9171dd65bbf108b9271"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:17c16e9a89c0b9f4ff2b143f232c5256383453ce7b55fe981598f9517adc8252"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:3730b1cd998a0cffc817602cc55e51f268fa97b3e38fa4bee578e3741474547a"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14201950513636f515dd455a06890e3a21d115b943cf6a8f5af67ad1413cfa1f"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f74e0053360e0eadd75193c0c379b6d7f51d074ebbff856bd41780e1a028b38d"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d5959e3df126931d28cd94dd5f0a708b7dd96019de80ab715fb922fd0c8a838d"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1927934dfba4658a97c2dab267e53ed239264d40fdd5b295fc317693543db85b"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-win32.whl", hash = "sha256:2f5bd22203e64e1732e149bfdd3083716d038abca294e4e2852159b3d893f9ec"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-win_amd64.whl", hash = "sha256:cd1f4caeca614b04db803566473f7db0971e7a88268f95e4a529b0ace699b949"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:f0884eaf6a2bbd7b03fea456e808909ee48dd4f7f455519d67defda791116368"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:6b900ae319b6f9ac1be0ca572dfb41c23a7ff6fcbf36e3be6d3054e1e4c60de6"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:3bbe79b134dfb7c98cf60e4962e31039bef824834cc7034bdf1886a2ed1097f9"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:77196c7ac8741d4a2aebb023bcc2964ac65ca44180fd791640889ab2afed3e47"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b65288ebe12e38dd3650fea65d82fcce0d35df1ae4a770b525c10119ee71962f"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:52b216c458458f6c292e12428916e80974c5113abc505a61e7b0b9f8932a785d"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88aa62303278aec45bbb26bf679269c7890346c37140ae30e39da1070c341e11"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-win32.whl", hash = "sha256:bb6802d63e42734d2baf02e1343377fe18590ed6a1f5ffbdebbbe0f8331f176b"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-win_amd64.whl", hash = "sha256:d5652d3a52a2e8e1d9bdf28fbd15e21b166e31b968cd7c8c604bf31611c0bb5b"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-linux_armv7l.whl", hash = "sha256:84e27206bd884be83a7fdcef8be3c90eb1591341c0ba9b0d25ec9db1043ba2f2"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:5eb63d9207b02a0fa30216907e1e7705cc2670f933e77236c6e0eb966ad3b4bf"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:95e49839d49e79187c43cd63af5c206dc5743a01d7d3d2f039772fa743cbb30c"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ae5cd2f89e33a529790bf8aa59a459484edb05e4f58d4cf78836b9dfa1fab43"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e1fd7301d762bf5984b7e7fb62fce82cff864d75f0a57e15cfd07ae1bd79133"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e38d5800151e6804d500e329f7ddfb615c50eee0c1607593e3147a4b21037e40"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:563a75924109e75809b2919e68d7e6ae7872e63d20258aae7899b14f6ff9e18b"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5f8934715577c9cc0c792b8a77f7d0dd2bb60e951161b10c5f46b60856673240"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:ed6cf7ff4a10c46f85340f9c68982f9efb29f51ee4b66828310fcdf3c2d7ffd1"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:1faa5006fe9e7b9e65c47bc23f7cd333fdcdd4ba35d44080303848266db5ab05"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:3b526dc5566161a3a17599753838b9cfbdd4cb15b6ad419aae8a5d12053fa8ae"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09db3688efd3499ce3c0b02c0bac0656abdab4cb99716f81ad879c08b92c56e"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:006ea0cc16e8bf8f307326e0556e1384f24abb402cc4e6a720aa1dfe8f268647"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b46ba0b6552b4375ede65e0c89491af532635347f78d52a72f8a027529e713ed"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ec6f561c86fe13cff3be16f297cc05e1aa1274294524743a4cf91d971866fbb0"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-win32.whl", hash = "sha256:c85391e06620d6e16a56341caae5007d0c6219beba065e1e288f2523fba6a335"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-win_amd64.whl", hash = "sha256:679cf2507090e010da73e5001665c76de2a5927b2e2110e459222b1c81cb10c2"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:0e87f105f1d152934759f8975ed002d5ce057b3cdf1cc6cb63fe6008671a27b9"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:bf9f281f528e0220558d57e09b4518dec148dcb250d78bd9cbb27e09edabb3f9"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:711314cb4c6c8b3d51bafaee380ffa5012bd0567ed68f1b0b1fc07492b27acab"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54bb570bd963905de3bda596b35e06026552705edebbb2cb737b57aa5252b9e5"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dce5f04676cf94e6e2d13d7f91ac2de79097d86675bc4d404a3c24dcc0332c88"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:98ddf871c614cc0ed331c7159ebbbf5040be562279677d3bb97c2e6083539f72"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f3aaf3b20c0f7063856b2432335af8f76cf580f898e04085548cde28332d6833"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-win32.whl", hash = "sha256:3dee3be61d9032f777a9b4e2696ea3d0748a582cb99c672b5d41ca66821e8c87"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-win_amd64.whl", hash = "sha256:f54b5181784464bd3573ae7dbcf053da18a4b7a75fe19960791f383be3d035ca"}, ] [package.dependencies] -grpcio = ">=1.60.1" +grpcio = ">=1.62.0" protobuf = ">=4.21.6,<5.0dev" setuptools = "*" @@ -1395,13 +1395,13 @@ test = ["eth-utils (>=1.0.1,<3)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>= [[package]] name = "identify" -version = "2.5.34" +version = "2.5.35" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.34-py2.py3-none-any.whl", hash = "sha256:a4316013779e433d08b96e5eabb7f641e6c7942e4ab5d4c509ebd2e7a8994aed"}, - {file = "identify-2.5.34.tar.gz", hash = "sha256:ee17bc9d499899bc9eaec1ac7bf2dc9eedd480db9d88b96d123d3b64a9d34f5d"}, + {file = "identify-2.5.35-py2.py3-none-any.whl", hash = "sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e"}, + {file = "identify-2.5.35.tar.gz", hash = "sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791"}, ] [package.extras] @@ -1785,13 +1785,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.6.1" +version = "3.6.2" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" files = [ - {file = "pre_commit-3.6.1-py2.py3-none-any.whl", hash = "sha256:9fe989afcf095d2c4796ce7c553cf28d4d4a9b9346de3cda079bcf40748454a4"}, - {file = "pre_commit-3.6.1.tar.gz", hash = "sha256:c90961d8aa706f75d60935aba09469a6b0bcb8345f127c3fbee4bdc5f114cf4b"}, + {file = "pre_commit-3.6.2-py2.py3-none-any.whl", hash = "sha256:ba637c2d7a670c10daedc059f5c49b5bd0aadbccfcd7ec15592cf9665117532c"}, + {file = "pre_commit-3.6.2.tar.gz", hash = "sha256:c3ef34f463045c88658c5b99f38c1e297abdcc0ff13f98d3370055fbbfabc67e"}, ] [package.dependencies] @@ -1803,22 +1803,22 @@ virtualenv = ">=20.10.0" [[package]] name = "protobuf" -version = "4.25.2" +version = "4.25.3" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "protobuf-4.25.2-cp310-abi3-win32.whl", hash = "sha256:b50c949608682b12efb0b2717f53256f03636af5f60ac0c1d900df6213910fd6"}, - {file = "protobuf-4.25.2-cp310-abi3-win_amd64.whl", hash = "sha256:8f62574857ee1de9f770baf04dde4165e30b15ad97ba03ceac65f760ff018ac9"}, - {file = "protobuf-4.25.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:2db9f8fa64fbdcdc93767d3cf81e0f2aef176284071507e3ede160811502fd3d"}, - {file = "protobuf-4.25.2-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:10894a2885b7175d3984f2be8d9850712c57d5e7587a2410720af8be56cdaf62"}, - {file = "protobuf-4.25.2-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:fc381d1dd0516343f1440019cedf08a7405f791cd49eef4ae1ea06520bc1c020"}, - {file = "protobuf-4.25.2-cp38-cp38-win32.whl", hash = "sha256:33a1aeef4b1927431d1be780e87b641e322b88d654203a9e9d93f218ee359e61"}, - {file = "protobuf-4.25.2-cp38-cp38-win_amd64.whl", hash = "sha256:47f3de503fe7c1245f6f03bea7e8d3ec11c6c4a2ea9ef910e3221c8a15516d62"}, - {file = "protobuf-4.25.2-cp39-cp39-win32.whl", hash = "sha256:5e5c933b4c30a988b52e0b7c02641760a5ba046edc5e43d3b94a74c9fc57c1b3"}, - {file = "protobuf-4.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:d66a769b8d687df9024f2985d5137a337f957a0916cf5464d1513eee96a63ff0"}, - {file = "protobuf-4.25.2-py3-none-any.whl", hash = "sha256:a8b7a98d4ce823303145bf3c1a8bdb0f2f4642a414b196f04ad9853ed0c8f830"}, - {file = "protobuf-4.25.2.tar.gz", hash = "sha256:fe599e175cb347efc8ee524bcd4b902d11f7262c0e569ececcb89995c15f0a5e"}, + {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, + {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, + {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, + {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, + {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, + {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, + {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, + {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, + {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, ] [[package]] @@ -1912,13 +1912,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" -version = "8.0.0" +version = "8.0.2" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"}, - {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"}, + {file = "pytest-8.0.2-py3-none-any.whl", hash = "sha256:edfaaef32ce5172d5466b5127b42e0d6d35ebbe4453f0e3505d96afd93f6b096"}, + {file = "pytest-8.0.2.tar.gz", hash = "sha256:d4051d623a2e0b7e51960ba963193b09ce6daeb9759a451844a21e4ddedfc1bd"}, ] [package.dependencies] @@ -1982,6 +1982,20 @@ files = [ [package.dependencies] pytest = ">=3.6.0" +[[package]] +name = "python-dotenv" +version = "1.0.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "pyunormalize" version = "15.1.0" @@ -2253,110 +2267,110 @@ test = ["hypothesis (==5.19.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "rpds-py" -version = "0.17.1" +version = "0.18.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.17.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4128980a14ed805e1b91a7ed551250282a8ddf8201a4e9f8f5b7e6225f54170d"}, - {file = "rpds_py-0.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ff1dcb8e8bc2261a088821b2595ef031c91d499a0c1b031c152d43fe0a6ecec8"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d65e6b4f1443048eb7e833c2accb4fa7ee67cc7d54f31b4f0555b474758bee55"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a71169d505af63bb4d20d23a8fbd4c6ce272e7bce6cc31f617152aa784436f29"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:436474f17733c7dca0fbf096d36ae65277e8645039df12a0fa52445ca494729d"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10162fe3f5f47c37ebf6d8ff5a2368508fe22007e3077bf25b9c7d803454d921"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:720215373a280f78a1814becb1312d4e4d1077b1202a56d2b0815e95ccb99ce9"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70fcc6c2906cfa5c6a552ba7ae2ce64b6c32f437d8f3f8eea49925b278a61453"}, - {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:91e5a8200e65aaac342a791272c564dffcf1281abd635d304d6c4e6b495f29dc"}, - {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:99f567dae93e10be2daaa896e07513dd4bf9c2ecf0576e0533ac36ba3b1d5394"}, - {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24e4900a6643f87058a27320f81336d527ccfe503984528edde4bb660c8c8d59"}, - {file = "rpds_py-0.17.1-cp310-none-win32.whl", hash = "sha256:0bfb09bf41fe7c51413f563373e5f537eaa653d7adc4830399d4e9bdc199959d"}, - {file = "rpds_py-0.17.1-cp310-none-win_amd64.whl", hash = "sha256:20de7b7179e2031a04042e85dc463a93a82bc177eeba5ddd13ff746325558aa6"}, - {file = "rpds_py-0.17.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:65dcf105c1943cba45d19207ef51b8bc46d232a381e94dd38719d52d3980015b"}, - {file = "rpds_py-0.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:01f58a7306b64e0a4fe042047dd2b7d411ee82e54240284bab63e325762c1147"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:071bc28c589b86bc6351a339114fb7a029f5cddbaca34103aa573eba7b482382"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae35e8e6801c5ab071b992cb2da958eee76340e6926ec693b5ff7d6381441745"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149c5cd24f729e3567b56e1795f74577aa3126c14c11e457bec1b1c90d212e38"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e796051f2070f47230c745d0a77a91088fbee2cc0502e9b796b9c6471983718c"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e820ee1004327609b28db8307acc27f5f2e9a0b185b2064c5f23e815f248f8"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1957a2ab607f9added64478a6982742eb29f109d89d065fa44e01691a20fc20a"}, - {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8587fd64c2a91c33cdc39d0cebdaf30e79491cc029a37fcd458ba863f8815383"}, - {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4dc889a9d8a34758d0fcc9ac86adb97bab3fb7f0c4d29794357eb147536483fd"}, - {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2953937f83820376b5979318840f3ee47477d94c17b940fe31d9458d79ae7eea"}, - {file = "rpds_py-0.17.1-cp311-none-win32.whl", hash = "sha256:1bfcad3109c1e5ba3cbe2f421614e70439f72897515a96c462ea657261b96518"}, - {file = "rpds_py-0.17.1-cp311-none-win_amd64.whl", hash = "sha256:99da0a4686ada4ed0f778120a0ea8d066de1a0a92ab0d13ae68492a437db78bf"}, - {file = "rpds_py-0.17.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1dc29db3900cb1bb40353772417800f29c3d078dbc8024fd64655a04ee3c4bdf"}, - {file = "rpds_py-0.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82ada4a8ed9e82e443fcef87e22a3eed3654dd3adf6e3b3a0deb70f03e86142a"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d36b2b59e8cc6e576f8f7b671e32f2ff43153f0ad6d0201250a7c07f25d570e"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3677fcca7fb728c86a78660c7fb1b07b69b281964673f486ae72860e13f512ad"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:516fb8c77805159e97a689e2f1c80655c7658f5af601c34ffdb916605598cda2"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df3b6f45ba4515632c5064e35ca7f31d51d13d1479673185ba8f9fefbbed58b9"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a967dd6afda7715d911c25a6ba1517975acd8d1092b2f326718725461a3d33f9"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dbbb95e6fc91ea3102505d111b327004d1c4ce98d56a4a02e82cd451f9f57140"}, - {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02866e060219514940342a1f84303a1ef7a1dad0ac311792fbbe19b521b489d2"}, - {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2528ff96d09f12e638695f3a2e0c609c7b84c6df7c5ae9bfeb9252b6fa686253"}, - {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd345a13ce06e94c753dab52f8e71e5252aec1e4f8022d24d56decd31e1b9b23"}, - {file = "rpds_py-0.17.1-cp312-none-win32.whl", hash = "sha256:2a792b2e1d3038daa83fa474d559acfd6dc1e3650ee93b2662ddc17dbff20ad1"}, - {file = "rpds_py-0.17.1-cp312-none-win_amd64.whl", hash = "sha256:292f7344a3301802e7c25c53792fae7d1593cb0e50964e7bcdcc5cf533d634e3"}, - {file = "rpds_py-0.17.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:8ffe53e1d8ef2520ebcf0c9fec15bb721da59e8ef283b6ff3079613b1e30513d"}, - {file = "rpds_py-0.17.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4341bd7579611cf50e7b20bb8c2e23512a3dc79de987a1f411cb458ab670eb90"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4eb548daf4836e3b2c662033bfbfc551db58d30fd8fe660314f86bf8510b93"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b686f25377f9c006acbac63f61614416a6317133ab7fafe5de5f7dc8a06d42eb"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e21b76075c01d65d0f0f34302b5a7457d95721d5e0667aea65e5bb3ab415c25"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b86b21b348f7e5485fae740d845c65a880f5d1eda1e063bc59bef92d1f7d0c55"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f175e95a197f6a4059b50757a3dca33b32b61691bdbd22c29e8a8d21d3914cae"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1701fc54460ae2e5efc1dd6350eafd7a760f516df8dbe51d4a1c79d69472fbd4"}, - {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9051e3d2af8f55b42061603e29e744724cb5f65b128a491446cc029b3e2ea896"}, - {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:7450dbd659fed6dd41d1a7d47ed767e893ba402af8ae664c157c255ec6067fde"}, - {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5a024fa96d541fd7edaa0e9d904601c6445e95a729a2900c5aec6555fe921ed6"}, - {file = "rpds_py-0.17.1-cp38-none-win32.whl", hash = "sha256:da1ead63368c04a9bded7904757dfcae01eba0e0f9bc41d3d7f57ebf1c04015a"}, - {file = "rpds_py-0.17.1-cp38-none-win_amd64.whl", hash = "sha256:841320e1841bb53fada91c9725e766bb25009cfd4144e92298db296fb6c894fb"}, - {file = "rpds_py-0.17.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:f6c43b6f97209e370124baf2bf40bb1e8edc25311a158867eb1c3a5d449ebc7a"}, - {file = "rpds_py-0.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7d63ec01fe7c76c2dbb7e972fece45acbb8836e72682bde138e7e039906e2c"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81038ff87a4e04c22e1d81f947c6ac46f122e0c80460b9006e6517c4d842a6ec"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:810685321f4a304b2b55577c915bece4c4a06dfe38f6e62d9cc1d6ca8ee86b99"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25f071737dae674ca8937a73d0f43f5a52e92c2d178330b4c0bb6ab05586ffa6"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa5bfb13f1e89151ade0eb812f7b0d7a4d643406caaad65ce1cbabe0a66d695f"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfe07308b311a8293a0d5ef4e61411c5c20f682db6b5e73de6c7c8824272c256"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a000133a90eea274a6f28adc3084643263b1e7c1a5a66eb0a0a7a36aa757ed74"}, - {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d0e8a6434a3fbf77d11448c9c25b2f25244226cfbec1a5159947cac5b8c5fa4"}, - {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:efa767c220d94aa4ac3a6dd3aeb986e9f229eaf5bce92d8b1b3018d06bed3772"}, - {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:dbc56680ecf585a384fbd93cd42bc82668b77cb525343170a2d86dafaed2a84b"}, - {file = "rpds_py-0.17.1-cp39-none-win32.whl", hash = "sha256:270987bc22e7e5a962b1094953ae901395e8c1e1e83ad016c5cfcfff75a15a3f"}, - {file = "rpds_py-0.17.1-cp39-none-win_amd64.whl", hash = "sha256:2a7b2f2f56a16a6d62e55354dd329d929560442bd92e87397b7a9586a32e3e76"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a3264e3e858de4fc601741498215835ff324ff2482fd4e4af61b46512dd7fc83"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f2f3b28b40fddcb6c1f1f6c88c6f3769cd933fa493ceb79da45968a21dccc920"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9584f8f52010295a4a417221861df9bea4c72d9632562b6e59b3c7b87a1522b7"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c64602e8be701c6cfe42064b71c84ce62ce66ddc6422c15463fd8127db3d8066"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:060f412230d5f19fc8c8b75f315931b408d8ebf56aec33ef4168d1b9e54200b1"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9412abdf0ba70faa6e2ee6c0cc62a8defb772e78860cef419865917d86c7342"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9737bdaa0ad33d34c0efc718741abaafce62fadae72c8b251df9b0c823c63b22"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9f0e4dc0f17dcea4ab9d13ac5c666b6b5337042b4d8f27e01b70fae41dd65c57"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1db228102ab9d1ff4c64148c96320d0be7044fa28bd865a9ce628ce98da5973d"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:d8bbd8e56f3ba25a7d0cf980fc42b34028848a53a0e36c9918550e0280b9d0b6"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:be22ae34d68544df293152b7e50895ba70d2a833ad9566932d750d3625918b82"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bf046179d011e6114daf12a534d874958b039342b347348a78b7cdf0dd9d6041"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:1a746a6d49665058a5896000e8d9d2f1a6acba8a03b389c1e4c06e11e0b7f40d"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0b8bf5b8db49d8fd40f54772a1dcf262e8be0ad2ab0206b5a2ec109c176c0a4"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f7f4cb1f173385e8a39c29510dd11a78bf44e360fb75610594973f5ea141028b"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7fbd70cb8b54fe745301921b0816c08b6d917593429dfc437fd024b5ba713c58"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bdf1303df671179eaf2cb41e8515a07fc78d9d00f111eadbe3e14262f59c3d0"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad059a4bd14c45776600d223ec194e77db6c20255578bb5bcdd7c18fd169361"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3664d126d3388a887db44c2e293f87d500c4184ec43d5d14d2d2babdb4c64cad"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:698ea95a60c8b16b58be9d854c9f993c639f5c214cf9ba782eca53a8789d6b19"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:c3d2010656999b63e628a3c694f23020322b4178c450dc478558a2b6ef3cb9bb"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:938eab7323a736533f015e6069a7d53ef2dcc841e4e533b782c2bfb9fb12d84b"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1e626b365293a2142a62b9a614e1f8e331b28f3ca57b9f05ebbf4cf2a0f0bdc5"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:380e0df2e9d5d5d339803cfc6d183a5442ad7ab3c63c2a0982e8c824566c5ccc"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b760a56e080a826c2e5af09002c1a037382ed21d03134eb6294812dda268c811"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5576ee2f3a309d2bb403ec292d5958ce03953b0e57a11d224c1f134feaf8c40f"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3c3461ebb4c4f1bbc70b15d20b565759f97a5aaf13af811fcefc892e9197ba"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:637b802f3f069a64436d432117a7e58fab414b4e27a7e81049817ae94de45d8d"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffee088ea9b593cc6160518ba9bd319b5475e5f3e578e4552d63818773c6f56a"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ac732390d529d8469b831949c78085b034bff67f584559340008d0f6041a049"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:93432e747fb07fa567ad9cc7aaadd6e29710e515aabf939dfbed8046041346c6"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7b7d9ca34542099b4e185b3c2a2b2eda2e318a7dbde0b0d83357a6d4421b5296"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:0387ce69ba06e43df54e43968090f3626e231e4bc9150e4c3246947567695f68"}, - {file = "rpds_py-0.17.1.tar.gz", hash = "sha256:0210b2668f24c078307260bf88bdac9d6f1093635df5123789bfee4d8d7fc8e7"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88"}, + {file = "rpds_py-0.18.0-cp310-none-win32.whl", hash = "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337"}, + {file = "rpds_py-0.18.0-cp310-none-win_amd64.whl", hash = "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836"}, + {file = "rpds_py-0.18.0-cp311-none-win32.whl", hash = "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1"}, + {file = "rpds_py-0.18.0-cp311-none-win_amd64.whl", hash = "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7"}, + {file = "rpds_py-0.18.0-cp312-none-win32.whl", hash = "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98"}, + {file = "rpds_py-0.18.0-cp312-none-win_amd64.whl", hash = "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594"}, + {file = "rpds_py-0.18.0-cp38-none-win32.whl", hash = "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e"}, + {file = "rpds_py-0.18.0-cp38-none-win_amd64.whl", hash = "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20"}, + {file = "rpds_py-0.18.0-cp39-none-win32.whl", hash = "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7"}, + {file = "rpds_py-0.18.0-cp39-none-win_amd64.whl", hash = "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f"}, + {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"}, ] [[package]] @@ -2371,19 +2385,19 @@ files = [ [[package]] name = "setuptools" -version = "69.1.0" +version = "69.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"}, - {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"}, + {file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"}, + {file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" @@ -2431,13 +2445,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.9.0" +version = "4.10.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, - {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, + {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, + {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] [[package]] @@ -2458,13 +2472,13 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.25.0" +version = "20.25.1" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"}, - {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"}, + {file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"}, + {file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"}, ] [package.dependencies] @@ -2698,4 +2712,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "7d6d14d38c3b61b57e268c236168e21a1b90e7fa0e36814a44468cace4f699a1" +content-hash = "531c4e91b09feb8097149a63a8cfde93152cd904df0f6616790d51ca8838dfe0" diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index ec42c2ce..d684a234 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -9,10 +9,11 @@ import grpc from google.protobuf import json_format -from pyinjective import constant from pyinjective.client.chain.grpc.chain_grpc_auth_api import ChainGrpcAuthApi from pyinjective.client.chain.grpc.chain_grpc_authz_api import ChainGrpcAuthZApi from pyinjective.client.chain.grpc.chain_grpc_bank_api import ChainGrpcBankApi +from pyinjective.client.chain.grpc.chain_grpc_distribution_api import ChainGrpcDistributionApi +from pyinjective.client.chain.grpc.chain_grpc_exchange_api import ChainGrpcExchangeApi from pyinjective.client.chain.grpc.chain_grpc_token_factory_api import ChainGrpcTokenFactoryApi from pyinjective.client.chain.grpc.chain_grpc_wasm_api import ChainGrpcWasmApi from pyinjective.client.chain.grpc_stream.chain_grpc_chain_stream import ChainGrpcChainStream @@ -179,6 +180,18 @@ def __init__( metadata_query_provider=self._chain_cookie_metadata_requestor ), ) + self.distribution_api = ChainGrpcDistributionApi( + channel=self.chain_channel, + metadata_provider=lambda: self.network.chain_metadata( + metadata_query_provider=self._chain_cookie_metadata_requestor + ), + ) + self.chain_exchange_api = ChainGrpcExchangeApi( + channel=self.chain_channel, + metadata_provider=lambda: self.network.chain_metadata( + metadata_query_provider=self._chain_cookie_metadata_requestor + ), + ) self.token_factory_api = ChainGrpcTokenFactoryApi( channel=self.chain_channel, metadata_provider=lambda: self.network.chain_metadata( @@ -573,6 +586,455 @@ async def fetch_send_enabled( ) -> Dict[str, Any]: return await self.bank_api.fetch_send_enabled(denoms=denoms, pagination=pagination) + async def fetch_validator_distribution_info(self, validator_address: str) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_distribution_info(validator_address=validator_address) + + async def fetch_validator_outstanding_rewards(self, validator_address: str) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_outstanding_rewards(validator_address=validator_address) + + async def fetch_validator_commission(self, validator_address: str) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_commission(validator_address=validator_address) + + async def fetch_validator_slashes( + self, + validator_address: str, + starting_height: Optional[int] = None, + ending_height: Optional[int] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_slashes( + validator_address=validator_address, + starting_height=starting_height, + ending_height=ending_height, + pagination=pagination, + ) + + async def fetch_delegation_rewards( + self, + delegator_address: str, + validator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegation_rewards( + delegator_address=delegator_address, + validator_address=validator_address, + ) + + async def fetch_delegation_total_rewards( + self, + delegator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegation_total_rewards( + delegator_address=delegator_address, + ) + + async def fetch_delegator_validators( + self, + delegator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegator_validators( + delegator_address=delegator_address, + ) + + async def fetch_delegator_withdraw_address( + self, + delegator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegator_withdraw_address( + delegator_address=delegator_address, + ) + + async def fetch_community_pool(self) -> Dict[str, Any]: + return await self.distribution_api.fetch_community_pool() + + # Exchange module + + async def fetch_subaccount_deposits( + self, + subaccount_id: Optional[str] = None, + subaccount_trader: Optional[str] = None, + subaccount_nonce: Optional[int] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_deposits( + subaccount_id=subaccount_id, + subaccount_trader=subaccount_trader, + subaccount_nonce=subaccount_nonce, + ) + + async def fetch_subaccount_deposit( + self, + subaccount_id: str, + denom: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_deposit( + subaccount_id=subaccount_id, + denom=denom, + ) + + async def fetch_exchange_balances(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_exchange_balances() + + async def fetch_aggregate_volume(self, account: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_volume(account=account) + + async def fetch_aggregate_volumes( + self, + accounts: Optional[List[str]] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_volumes( + accounts=accounts, + market_ids=market_ids, + ) + + async def fetch_aggregate_market_volume( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_market_volume( + market_id=market_id, + ) + + async def fetch_aggregate_market_volumes( + self, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_market_volumes( + market_ids=market_ids, + ) + + async def fetch_denom_decimal(self, denom: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_denom_decimal(denom=denom) + + async def fetch_denom_decimals(self, denoms: Optional[List[str]] = None) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_denom_decimals(denoms=denoms) + + async def fetch_chain_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_markets( + status=status, + market_ids=market_ids, + ) + + async def fetch_chain_spot_market( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_market( + market_id=market_id, + ) + + async def fetch_chain_full_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_full_spot_markets( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + + async def fetch_chain_full_spot_market( + self, + market_id: str, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_full_spot_market( + market_id=market_id, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + + async def fetch_chain_spot_orderbook( + self, + market_id: str, + order_side: Optional[str] = None, + limit_cumulative_notional: Optional[str] = None, + limit_cumulative_quantity: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + # Order side could be "Side_Unspecified", "Buy", "Sell" + return await self.chain_exchange_api.fetch_spot_orderbook( + market_id=market_id, + order_side=order_side, + limit_cumulative_notional=limit_cumulative_notional, + limit_cumulative_quantity=limit_cumulative_quantity, + pagination=pagination, + ) + + async def fetch_chain_trader_spot_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_spot_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_chain_account_address_spot_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_account_address_spot_orders( + market_id=market_id, + account_address=account_address, + ) + + async def fetch_chain_spot_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_orders_by_hashes( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + + async def fetch_chain_subaccount_orders( + self, + subaccount_id: str, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_orders( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_chain_trader_spot_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_spot_transient_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_spot_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_mid_price_and_tob( + market_id=market_id, + ) + + async def fetch_derivative_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_mid_price_and_tob( + market_id=market_id, + ) + + async def fetch_chain_derivative_orderbook( + self, + market_id: str, + limit_cumulative_notional: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_orderbook( + market_id=market_id, + limit_cumulative_notional=limit_cumulative_notional, + pagination=pagination, + ) + + async def fetch_chain_trader_derivative_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_derivative_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_chain_account_address_derivative_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_account_address_derivative_orders( + market_id=market_id, + account_address=account_address, + ) + + async def fetch_chain_derivative_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_orders_by_hashes( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + + async def fetch_chain_trader_derivative_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_derivative_transient_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_chain_derivative_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_markets( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + + async def fetch_chain_derivative_market( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_market( + market_id=market_id, + ) + + async def fetch_derivative_market_address(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_market_address(market_id=market_id) + + async def fetch_subaccount_trade_nonce(self, subaccount_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_trade_nonce(subaccount_id=subaccount_id) + + async def fetch_chain_positions(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_positions() + + async def fetch_chain_subaccount_positions(self, subaccount_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_positions(subaccount_id=subaccount_id) + + async def fetch_chain_subaccount_position_in_market(self, subaccount_id: str, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_chain_subaccount_effective_position_in_market( + self, subaccount_id: str, market_id: str + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_effective_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_chain_perpetual_market_info(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_perpetual_market_info(market_id=market_id) + + async def fetch_chain_expiry_futures_market_info(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_expiry_futures_market_info(market_id=market_id) + + async def fetch_chain_perpetual_market_funding(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_perpetual_market_funding(market_id=market_id) + + async def fetch_subaccount_order_metadata(self, subaccount_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_order_metadata(subaccount_id=subaccount_id) + + async def fetch_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trade_reward_points( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + + async def fetch_pending_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_pending_trade_reward_points( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + + async def fetch_trade_reward_campaign(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trade_reward_campaign() + + async def fetch_fee_discount_account_info(self, account: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_fee_discount_account_info(account=account) + + async def fetch_fee_discount_schedule(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_fee_discount_schedule() + + async def fetch_balance_mismatches(self, dust_factor: int) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_balance_mismatches(dust_factor=dust_factor) + + async def fetch_balance_with_balance_holds(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_balance_with_balance_holds() + + async def fetch_fee_discount_tier_statistics(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_fee_discount_tier_statistics() + + async def fetch_mito_vault_infos(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_mito_vault_infos() + + async def fetch_market_id_from_vault(self, vault_address: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_market_id_from_vault(vault_address=vault_address) + + async def fetch_historical_trade_records(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_historical_trade_records(market_id=market_id) + + async def fetch_is_opted_out_of_rewards(self, account: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_is_opted_out_of_rewards(account=account) + + async def fetch_opted_out_of_rewards_accounts(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_opted_out_of_rewards_accounts() + + async def fetch_market_volatility( + self, + market_id: str, + trade_grouping_sec: Optional[int] = None, + max_age: Optional[int] = None, + include_raw_history: Optional[bool] = None, + include_metadata: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_market_volatility( + market_id=market_id, + trade_grouping_sec=trade_grouping_sec, + max_age=max_age, + include_raw_history=include_raw_history, + include_metadata=include_metadata, + ) + + async def fetch_chain_binary_options_markets(self, status: Optional[str] = None) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_binary_options_markets(status=status) + + async def fetch_trader_derivative_conditional_orders( + self, + subaccount_id: Optional[str] = None, + market_id: Optional[str] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_derivative_conditional_orders( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_market_atomic_execution_fee_multiplier( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_market_atomic_execution_fee_multiplier( + market_id=market_id, + ) + # Injective Exchange client methods # Auction RPC @@ -2659,22 +3121,13 @@ async def _initialize_tokens_and_markets(self): ) for market_info in valid_markets: - ticker = market_info["ticker"] - if "/" in ticker: - base_token_symbol, quote_token_symbol = ticker.split(constant.TICKER_TOKENS_SEPARATOR) - else: - base_token_symbol = market_info["baseTokenMeta"]["symbol"] - quote_token_symbol = market_info["quoteTokenMeta"]["symbol"] - base_token = self._token_representation( - symbol=base_token_symbol, token_meta=market_info["baseTokenMeta"], denom=market_info["baseDenom"], tokens_by_denom=tokens_by_denom, tokens_by_symbol=tokens_by_symbol, ) quote_token = self._token_representation( - symbol=quote_token_symbol, token_meta=market_info["quoteTokenMeta"], denom=market_info["quoteDenom"], tokens_by_denom=tokens_by_denom, @@ -2704,10 +3157,7 @@ async def _initialize_tokens_and_markets(self): ) for market_info in valid_markets: - quote_token_symbol = market_info["quoteTokenMeta"]["symbol"] - quote_token = self._token_representation( - symbol=quote_token_symbol, token_meta=market_info["quoteTokenMeta"], denom=market_info["quoteDenom"], tokens_by_denom=tokens_by_denom, @@ -2769,7 +3219,6 @@ async def _initialize_tokens_and_markets(self): def _token_representation( self, - symbol: str, token_meta: Dict[str, Any], denom: str, tokens_by_denom: Dict[str, Token], @@ -2777,14 +3226,14 @@ def _token_representation( ) -> Token: if denom not in tokens_by_denom: unique_symbol = denom - for symbol_candidate in [symbol, token_meta["symbol"], token_meta["name"]]: + for symbol_candidate in [token_meta["symbol"], token_meta["name"]]: if symbol_candidate not in tokens_by_symbol: unique_symbol = symbol_candidate break token = Token( name=token_meta["name"], - symbol=symbol, + symbol=token_meta["symbol"], denom=denom, address=token_meta["address"], decimals=token_meta["decimals"], diff --git a/pyinjective/client/chain/grpc/chain_grpc_distribution_api.py b/pyinjective/client/chain/grpc/chain_grpc_distribution_api.py new file mode 100644 index 00000000..e7da0966 --- /dev/null +++ b/pyinjective/client/chain/grpc/chain_grpc_distribution_api.py @@ -0,0 +1,109 @@ +from typing import Any, Callable, Dict, Optional + +from grpc.aio import Channel + +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + query_pb2 as distribution_query_pb, + query_pb2_grpc as distribution_query_grpc, +) +from pyinjective.utils.grpc_api_request_assistant import GrpcApiRequestAssistant + + +class ChainGrpcDistributionApi: + def __init__(self, channel: Channel, metadata_provider: Callable): + self._stub = distribution_query_grpc.QueryStub(channel) + self._assistant = GrpcApiRequestAssistant(metadata_provider=metadata_provider) + + async def fetch_module_params(self) -> Dict[str, Any]: + request = distribution_query_pb.QueryParamsRequest() + response = await self._execute_call(call=self._stub.Params, request=request) + + return response + + async def fetch_validator_distribution_info(self, validator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryValidatorDistributionInfoRequest(validator_address=validator_address) + response = await self._execute_call(call=self._stub.ValidatorDistributionInfo, request=request) + + return response + + async def fetch_validator_outstanding_rewards(self, validator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryValidatorOutstandingRewardsRequest(validator_address=validator_address) + response = await self._execute_call(call=self._stub.ValidatorOutstandingRewards, request=request) + + return response + + async def fetch_validator_commission(self, validator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryValidatorCommissionRequest(validator_address=validator_address) + response = await self._execute_call(call=self._stub.ValidatorCommission, request=request) + + return response + + async def fetch_validator_slashes( + self, + validator_address: str, + starting_height: Optional[int] = None, + ending_height: Optional[int] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + pagination_request = None + if pagination is not None: + pagination_request = pagination.create_pagination_request() + request = distribution_query_pb.QueryValidatorSlashesRequest( + validator_address=validator_address, + starting_height=starting_height, + ending_height=ending_height, + pagination=pagination_request, + ) + response = await self._execute_call(call=self._stub.ValidatorSlashes, request=request) + + return response + + async def fetch_delegation_rewards( + self, + delegator_address: str, + validator_address: str, + ) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegationRewardsRequest( + delegator_address=delegator_address, + validator_address=validator_address, + ) + response = await self._execute_call(call=self._stub.DelegationRewards, request=request) + + return response + + async def fetch_delegation_total_rewards( + self, + delegator_address: str, + ) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegationTotalRewardsRequest( + delegator_address=delegator_address, + ) + response = await self._execute_call(call=self._stub.DelegationTotalRewards, request=request) + + return response + + async def fetch_delegator_validators(self, delegator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegatorValidatorsRequest( + delegator_address=delegator_address, + ) + response = await self._execute_call(call=self._stub.DelegatorValidators, request=request) + + return response + + async def fetch_delegator_withdraw_address(self, delegator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegatorWithdrawAddressRequest( + delegator_address=delegator_address, + ) + response = await self._execute_call(call=self._stub.DelegatorWithdrawAddress, request=request) + + return response + + async def fetch_community_pool(self) -> Dict[str, Any]: + request = distribution_query_pb.QueryCommunityPoolRequest() + response = await self._execute_call(call=self._stub.CommunityPool, request=request) + + return response + + async def _execute_call(self, call: Callable, request) -> Dict[str, Any]: + return await self._assistant.execute_call(call=call, request=request) diff --git a/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py b/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py new file mode 100644 index 00000000..b79e8569 --- /dev/null +++ b/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py @@ -0,0 +1,578 @@ +from typing import Any, Callable, Dict, List, Optional + +from grpc.aio import Channel + +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.proto.injective.exchange.v1beta1 import ( + query_pb2 as exchange_query_pb, + query_pb2_grpc as exchange_query_grpc, +) +from pyinjective.utils.grpc_api_request_assistant import GrpcApiRequestAssistant + + +class ChainGrpcExchangeApi: + def __init__(self, channel: Channel, metadata_provider: Callable): + self._stub = exchange_query_grpc.QueryStub(channel) + self._assistant = GrpcApiRequestAssistant(metadata_provider=metadata_provider) + + async def fetch_exchange_params(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryExchangeParamsRequest() + response = await self._execute_call(call=self._stub.QueryExchangeParams, request=request) + + return response + + async def fetch_subaccount_deposits( + self, + subaccount_id: Optional[str] = None, + subaccount_trader: Optional[str] = None, + subaccount_nonce: Optional[int] = None, + ) -> Dict[str, Any]: + subaccount = None + if subaccount_trader is not None or subaccount_nonce is not None: + subaccount = exchange_query_pb.Subaccount( + trader=subaccount_trader, + subaccount_nonce=subaccount_nonce, + ) + + request = exchange_query_pb.QuerySubaccountDepositsRequest(subaccount_id=subaccount_id, subaccount=subaccount) + response = await self._execute_call(call=self._stub.SubaccountDeposits, request=request) + + return response + + async def fetch_subaccount_deposit( + self, + subaccount_id: str, + denom: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountDepositRequest( + subaccount_id=subaccount_id, + denom=denom, + ) + response = await self._execute_call(call=self._stub.SubaccountDeposit, request=request) + + return response + + async def fetch_exchange_balances(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryExchangeBalancesRequest() + response = await self._execute_call(call=self._stub.ExchangeBalances, request=request) + + return response + + async def fetch_aggregate_volume(self, account: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateVolumeRequest(account=account) + response = await self._execute_call(call=self._stub.AggregateVolume, request=request) + + return response + + async def fetch_aggregate_volumes( + self, + accounts: Optional[List[str]] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateVolumesRequest(accounts=accounts, market_ids=market_ids) + response = await self._execute_call(call=self._stub.AggregateVolumes, request=request) + + return response + + async def fetch_aggregate_market_volume(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateMarketVolumeRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.AggregateMarketVolume, request=request) + + return response + + async def fetch_aggregate_market_volumes(self, market_ids: Optional[List[str]] = None) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateMarketVolumesRequest(market_ids=market_ids) + response = await self._execute_call(call=self._stub.AggregateMarketVolumes, request=request) + + return response + + async def fetch_denom_decimal(self, denom: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryDenomDecimalRequest(denom=denom) + response = await self._execute_call(call=self._stub.DenomDecimal, request=request) + + return response + + async def fetch_denom_decimals(self, denoms: Optional[List[str]] = None) -> Dict[str, Any]: + request = exchange_query_pb.QueryDenomDecimalsRequest(denoms=denoms) + response = await self._execute_call(call=self._stub.DenomDecimals, request=request) + + return response + + async def fetch_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotMarketsRequest( + status=status, + market_ids=market_ids, + ) + response = await self._execute_call(call=self._stub.SpotMarkets, request=request) + + return response + + async def fetch_spot_market(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotMarketRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.SpotMarket, request=request) + + return response + + async def fetch_full_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFullSpotMarketsRequest( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + response = await self._execute_call(call=self._stub.FullSpotMarkets, request=request) + + return response + + async def fetch_full_spot_market( + self, + market_id: str, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFullSpotMarketRequest( + market_id=market_id, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + response = await self._execute_call(call=self._stub.FullSpotMarket, request=request) + + return response + + async def fetch_spot_orderbook( + self, + market_id: str, + order_side: Optional[str] = None, + limit_cumulative_notional: Optional[str] = None, + limit_cumulative_quantity: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + limit = None + if pagination is not None: + limit = pagination.limit + request = exchange_query_pb.QuerySpotOrderbookRequest( + market_id=market_id, + order_side=order_side, + limit=limit, + limit_cumulative_notional=limit_cumulative_notional, + limit_cumulative_quantity=limit_cumulative_quantity, + ) + response = await self._execute_call(call=self._stub.SpotOrderbook, request=request) + + return response + + async def fetch_trader_spot_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderSpotOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderSpotOrders, request=request) + + return response + + async def fetch_account_address_spot_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryAccountAddressSpotOrdersRequest( + market_id=market_id, + account_address=account_address, + ) + response = await self._execute_call(call=self._stub.AccountAddressSpotOrders, request=request) + + return response + + async def fetch_spot_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotOrdersByHashesRequest( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + response = await self._execute_call(call=self._stub.SpotOrdersByHashes, request=request) + + return response + + async def fetch_subaccount_orders( + self, + subaccount_id: str, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountOrdersRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SubaccountOrders, request=request) + + return response + + async def fetch_trader_spot_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderSpotOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderSpotTransientOrders, request=request) + + return response + + async def fetch_spot_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotMidPriceAndTOBRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SpotMidPriceAndTOB, request=request) + + return response + + async def fetch_derivative_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMidPriceAndTOBRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.DerivativeMidPriceAndTOB, request=request) + + return response + + async def fetch_derivative_orderbook( + self, + market_id: str, + limit_cumulative_notional: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + limit = None + if pagination is not None: + limit = pagination.limit + request = exchange_query_pb.QueryDerivativeOrderbookRequest( + market_id=market_id, + limit=limit, + limit_cumulative_notional=limit_cumulative_notional, + ) + response = await self._execute_call(call=self._stub.DerivativeOrderbook, request=request) + + return response + + async def fetch_trader_derivative_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderDerivativeOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderDerivativeOrders, request=request) + + return response + + async def fetch_account_address_derivative_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryAccountAddressDerivativeOrdersRequest( + market_id=market_id, + account_address=account_address, + ) + response = await self._execute_call(call=self._stub.AccountAddressDerivativeOrders, request=request) + + return response + + async def fetch_derivative_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeOrdersByHashesRequest( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + response = await self._execute_call(call=self._stub.DerivativeOrdersByHashes, request=request) + + return response + + async def fetch_trader_derivative_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderDerivativeOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderDerivativeTransientOrders, request=request) + + return response + + async def fetch_derivative_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMarketsRequest( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + response = await self._execute_call(call=self._stub.DerivativeMarkets, request=request) + + return response + + async def fetch_derivative_market( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMarketRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.DerivativeMarket, request=request) + + return response + + async def fetch_derivative_market_address( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMarketAddressRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.DerivativeMarketAddress, request=request) + + return response + + async def fetch_subaccount_trade_nonce(self, subaccount_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountTradeNonceRequest(subaccount_id=subaccount_id) + response = await self._execute_call(call=self._stub.SubaccountTradeNonce, request=request) + + return response + + async def fetch_positions(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryPositionsRequest() + response = await self._execute_call(call=self._stub.Positions, request=request) + + return response + + async def fetch_subaccount_positions(self, subaccount_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountPositionsRequest(subaccount_id=subaccount_id) + response = await self._execute_call(call=self._stub.SubaccountPositions, request=request) + + return response + + async def fetch_subaccount_position_in_market(self, subaccount_id: str, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountPositionInMarketRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SubaccountPositionInMarket, request=request) + + return response + + async def fetch_subaccount_effective_position_in_market(self, subaccount_id: str, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountEffectivePositionInMarketRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SubaccountEffectivePositionInMarket, request=request) + + return response + + async def fetch_perpetual_market_info(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryPerpetualMarketInfoRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.PerpetualMarketInfo, request=request) + + return response + + async def fetch_expiry_futures_market_info(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryExpiryFuturesMarketInfoRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.ExpiryFuturesMarketInfo, request=request) + + return response + + async def fetch_perpetual_market_funding(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryPerpetualMarketFundingRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.PerpetualMarketFunding, request=request) + + return response + + async def fetch_subaccount_order_metadata(self, subaccount_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountOrderMetadataRequest(subaccount_id=subaccount_id) + response = await self._execute_call(call=self._stub.SubaccountOrderMetadata, request=request) + + return response + + async def fetch_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTradeRewardPointsRequest( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + response = await self._execute_call(call=self._stub.TradeRewardPoints, request=request) + + return response + + async def fetch_pending_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTradeRewardPointsRequest( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + response = await self._execute_call(call=self._stub.PendingTradeRewardPoints, request=request) + + return response + + async def fetch_trade_reward_campaign(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryTradeRewardCampaignRequest() + response = await self._execute_call(call=self._stub.TradeRewardCampaign, request=request) + + return response + + async def fetch_fee_discount_account_info( + self, + account: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFeeDiscountAccountInfoRequest(account=account) + response = await self._execute_call(call=self._stub.FeeDiscountAccountInfo, request=request) + + return response + + async def fetch_fee_discount_schedule(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryFeeDiscountScheduleRequest() + response = await self._execute_call(call=self._stub.FeeDiscountSchedule, request=request) + + return response + + async def fetch_balance_mismatches(self, dust_factor: int) -> Dict[str, Any]: + request = exchange_query_pb.QueryBalanceMismatchesRequest(dust_factor=dust_factor) + response = await self._execute_call(call=self._stub.BalanceMismatches, request=request) + + return response + + async def fetch_balance_with_balance_holds(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryBalanceWithBalanceHoldsRequest() + response = await self._execute_call(call=self._stub.BalanceWithBalanceHolds, request=request) + + return response + + async def fetch_fee_discount_tier_statistics(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryFeeDiscountTierStatisticsRequest() + response = await self._execute_call(call=self._stub.FeeDiscountTierStatistics, request=request) + + return response + + async def fetch_mito_vault_infos(self) -> Dict[str, Any]: + request = exchange_query_pb.MitoVaultInfosRequest() + response = await self._execute_call(call=self._stub.MitoVaultInfos, request=request) + + return response + + async def fetch_market_id_from_vault(self, vault_address: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryMarketIDFromVaultRequest(vault_address=vault_address) + response = await self._execute_call(call=self._stub.QueryMarketIDFromVault, request=request) + + return response + + async def fetch_historical_trade_records(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryHistoricalTradeRecordsRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.HistoricalTradeRecords, request=request) + + return response + + async def fetch_is_opted_out_of_rewards(self, account: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryIsOptedOutOfRewardsRequest(account=account) + response = await self._execute_call(call=self._stub.IsOptedOutOfRewards, request=request) + + return response + + async def fetch_opted_out_of_rewards_accounts(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryOptedOutOfRewardsAccountsRequest() + response = await self._execute_call(call=self._stub.OptedOutOfRewardsAccounts, request=request) + + return response + + async def fetch_market_volatility( + self, + market_id: str, + trade_grouping_sec: Optional[int] = None, + max_age: Optional[int] = None, + include_raw_history: Optional[bool] = None, + include_metadata: Optional[bool] = None, + ) -> Dict[str, Any]: + trade_history_options = exchange_query_pb.TradeHistoryOptions() + if trade_grouping_sec is not None: + trade_history_options.trade_grouping_sec = trade_grouping_sec + if max_age is not None: + trade_history_options.max_age = max_age + if include_raw_history is not None: + trade_history_options.include_raw_history = include_raw_history + if include_metadata is not None: + trade_history_options.include_metadata = include_metadata + request = exchange_query_pb.QueryMarketVolatilityRequest( + market_id=market_id, trade_history_options=trade_history_options + ) + response = await self._execute_call(call=self._stub.MarketVolatility, request=request) + + return response + + async def fetch_binary_options_markets(self, status: Optional[str] = None) -> Dict[str, Any]: + request = exchange_query_pb.QueryBinaryMarketsRequest(status=status) + response = await self._execute_call(call=self._stub.BinaryOptionsMarkets, request=request) + + return response + + async def fetch_trader_derivative_conditional_orders( + self, + subaccount_id: Optional[str] = None, + market_id: Optional[str] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderDerivativeConditionalOrdersRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.TraderDerivativeConditionalOrders, request=request) + + return response + + async def fetch_market_atomic_execution_fee_multiplier( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryMarketAtomicExecutionFeeMultiplierRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.MarketAtomicExecutionFeeMultiplier, request=request) + + return response + + async def _execute_call(self, call: Callable, request) -> Dict[str, Any]: + return await self._assistant.execute_call(call=call, request=request) diff --git a/pyinjective/composer.py b/pyinjective/composer.py index 720920d1..9a0807c9 100644 --- a/pyinjective/composer.py +++ b/pyinjective/composer.py @@ -3,6 +3,7 @@ from decimal import Decimal from time import time from typing import Any, Dict, List, Optional +from warnings import warn from google.protobuf import any_pb2, json_format, timestamp_pb2 @@ -12,8 +13,11 @@ from pyinjective.core.token import Token from pyinjective.proto.cosmos.authz.v1beta1 import authz_pb2 as cosmos_authz_pb, tx_pb2 as cosmos_authz_tx_pb from pyinjective.proto.cosmos.bank.v1beta1 import bank_pb2 as bank_pb, tx_pb2 as cosmos_bank_tx_pb -from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as cosmos_dot_base_dot_v1beta1_dot_coin__pb2 -from pyinjective.proto.cosmos.distribution.v1beta1 import tx_pb2 as cosmos_distribution_tx_pb +from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as base_coin_pb +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + distribution_pb2 as cosmos_distribution_pb2, + tx_pb2 as cosmos_distribution_tx_pb, +) from pyinjective.proto.cosmos.gov.v1beta1 import tx_pb2 as cosmos_gov_tx_pb from pyinjective.proto.cosmos.staking.v1beta1 import tx_pb2 as cosmos_staking_tx_pb from pyinjective.proto.cosmwasm.wasm.v1 import tx_pb2 as wasm_tx_pb @@ -21,15 +25,19 @@ from pyinjective.proto.injective.auction.v1beta1 import tx_pb2 as injective_auction_tx_pb from pyinjective.proto.injective.exchange.v1beta1 import ( authz_pb2 as injective_authz_pb, - exchange_pb2 as injective_dot_exchange_dot_v1beta1_dot_exchange__pb2, + exchange_pb2 as injective_exchange_pb, tx_pb2 as injective_exchange_tx_pb, ) from pyinjective.proto.injective.insurance.v1beta1 import tx_pb2 as injective_insurance_tx_pb -from pyinjective.proto.injective.oracle.v1beta1 import tx_pb2 as injective_oracle_tx_pb +from pyinjective.proto.injective.oracle.v1beta1 import ( + oracle_pb2 as injective_oracle_pb, + tx_pb2 as injective_oracle_tx_pb, +) from pyinjective.proto.injective.peggy.v1 import msgs_pb2 as injective_peggy_tx_pb from pyinjective.proto.injective.stream.v1beta1 import query_pb2 as chain_stream_query from pyinjective.proto.injective.tokenfactory.v1beta1 import tx_pb2 as token_factory_tx_pb from pyinjective.proto.injective.wasmx.v1 import tx_pb2 as wasmx_tx_pb +from pyinjective.utils.denom import Denom REQUEST_TO_RESPONSE_TYPE_MAP = { "MsgCreateSpotLimitOrder": injective_exchange_tx_pb.MsgCreateSpotLimitOrderResponse, @@ -129,37 +137,59 @@ def __init__( self.tokens = tokens def Coin(self, amount: int, denom: str): - return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=str(amount), denom=denom) - - def get_order_mask(self, **kwargs): - order_mask = 0 - - if kwargs.get("is_conditional"): - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.CONDITIONAL - else: - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.REGULAR - - if kwargs.get("order_direction") == "buy": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.DIRECTION_BUY_OR_HIGHER - - elif kwargs.get("order_direction") == "sell": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.DIRECTION_SELL_OR_LOWER - - if kwargs.get("order_type") == "market": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.TYPE_MARKET - - elif kwargs.get("order_type") == "limit": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.TYPE_LIMIT + """ + This method is deprecated and will be removed soon. Please use `coin` instead + """ + warn("This method is deprecated. Use coin instead", DeprecationWarning, stacklevel=2) + return base_coin_pb.Coin(amount=str(amount), denom=denom) - if order_mask == 0: - order_mask = 1 + def coin(self, amount: int, denom: str): + """ + This method create an instance of Coin gRPC type, considering the amount is already expressed in chain format + """ + formatted_amount_string = str(int(amount)) + return base_coin_pb.Coin(amount=formatted_amount_string, denom=denom) - return order_mask + def create_coin_amount(self, amount: Decimal, token_name: str): + """ + This method create an instance of Coin gRPC type, considering the amount is already expressed in chain format + """ + token = self.tokens[token_name] + chain_amount = token.chain_formatted_value(human_readable_value=amount) + return self.coin(amount=int(chain_amount), denom=token.denom) def OrderData( self, market_id: str, subaccount_id: str, order_hash: Optional[str] = None, cid: Optional[str] = None, **kwargs ): - order_mask = self.get_order_mask(**kwargs) + """ + This method is deprecated and will be removed soon. Please use `order_data` instead + """ + warn("This method is deprecated. Use order_data instead", DeprecationWarning, stacklevel=2) + + is_conditional = kwargs.get("is_conditional", False) + is_buy = kwargs.get("order_direction", "buy") == "buy" + is_market_order = kwargs.get("order_type", "limit") == "market" + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) + + return injective_exchange_tx_pb.OrderData( + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + order_mask=order_mask, + cid=cid, + ) + + def order_data( + self, + market_id: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + is_conditional: Optional[bool] = False, + is_buy: Optional[bool] = False, + is_market_order: Optional[bool] = False, + ) -> injective_exchange_tx_pb.OrderData: + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) return injective_exchange_tx_pb.OrderData( market_id=market_id, @@ -179,6 +209,11 @@ def SpotOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `spot_order` instead + """ + warn("This method is deprecated. Use spot_order instead", DeprecationWarning, stacklevel=2) + market = self.spot_markets[market_id] # prepare values @@ -187,20 +222,20 @@ def SpotOrder( trigger_price = market.price_to_chain_format(human_readable_value=Decimal(0)) if kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY + order_type = injective_exchange_pb.OrderType.BUY elif not kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL + order_type = injective_exchange_pb.OrderType.SELL elif kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY_PO + order_type = injective_exchange_pb.OrderType.BUY_PO elif not kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL_PO + order_type = injective_exchange_pb.OrderType.SELL_PO - return injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.SpotOrder( + return injective_exchange_pb.SpotOrder( market_id=market_id, - order_info=injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderInfo( + order_info=injective_exchange_pb.OrderInfo( subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=str(int(price)), @@ -211,6 +246,50 @@ def SpotOrder( trigger_price=str(int(trigger_price)), ) + def spot_order( + self, + market_id: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_pb.SpotOrder: + market = self.spot_markets[market_id] + + chain_quantity = f"{market.quantity_to_chain_format(human_readable_value=quantity).normalize():f}" + chain_price = f"{market.price_to_chain_format(human_readable_value=price).normalize():f}" + + trigger_price = trigger_price or Decimal(0) + chain_trigger_price = f"{market.price_to_chain_format(human_readable_value=trigger_price).normalize():f}" + + chain_order_type = injective_exchange_pb.OrderType.Value(order_type) + + return injective_exchange_pb.SpotOrder( + market_id=market_id, + order_info=injective_exchange_pb.OrderInfo( + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=chain_price, + quantity=chain_quantity, + cid=cid, + ), + order_type=chain_order_type, + trigger_price=chain_trigger_price, + ) + + def calculate_margin( + self, quantity: Decimal, price: Decimal, leverage: Decimal, is_reduce_only: bool = False + ) -> Decimal: + if is_reduce_only: + margin = Decimal(0) + else: + margin = quantity * price / leverage + + return margin + def DerivativeOrder( self, market_id: str, @@ -222,6 +301,10 @@ def DerivativeOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `derivative_order` instead + """ + warn("This method is deprecated. Use derivative_order instead", DeprecationWarning, stacklevel=2) market = self.derivative_markets[market_id] if kwargs.get("is_reduce_only", False): @@ -239,32 +322,32 @@ def DerivativeOrder( trigger_price = market.price_to_chain_format(human_readable_value=Decimal(str(trigger_price))) if kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY + order_type = injective_exchange_pb.OrderType.BUY elif not kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL + order_type = injective_exchange_pb.OrderType.SELL elif kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY_PO + order_type = injective_exchange_pb.OrderType.BUY_PO elif not kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL_PO + order_type = injective_exchange_pb.OrderType.SELL_PO elif kwargs.get("stop_buy"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.STOP_BUY + order_type = injective_exchange_pb.OrderType.STOP_BUY elif kwargs.get("stop_sell"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.STOP_SEll + order_type = injective_exchange_pb.OrderType.STOP_SEll elif kwargs.get("take_buy"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.TAKE_BUY + order_type = injective_exchange_pb.OrderType.TAKE_BUY elif kwargs.get("take_sell"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.TAKE_SELL + order_type = injective_exchange_pb.OrderType.TAKE_SELL - return injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.DerivativeOrder( + return injective_exchange_pb.DerivativeOrder( market_id=market_id, - order_info=injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderInfo( + order_info=injective_exchange_pb.OrderInfo( subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=str(int(price)), @@ -276,87 +359,291 @@ def DerivativeOrder( trigger_price=str(int(trigger_price)), ) - def BinaryOptionsOrder( + def derivative_order( self, market_id: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, cid: Optional[str] = None, - **kwargs, - ): - market = self.binary_option_markets[market_id] - denom = kwargs.get("denom", None) + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_pb.DerivativeOrder: + market = self.derivative_markets[market_id] - if kwargs.get("is_reduce_only", False): - margin = 0 - else: - margin = market.calculate_margin_in_chain_format( - human_readable_quantity=Decimal(str(quantity)), - human_readable_price=Decimal(str(price)), - is_buy=kwargs["is_buy"], - special_denom=denom, - ) + chain_quantity = market.quantity_to_chain_format(human_readable_value=quantity) + chain_price = market.price_to_chain_format(human_readable_value=price) + chain_margin = market.margin_to_chain_format(human_readable_value=margin) - # prepare values - price = market.price_to_chain_format(human_readable_value=Decimal(str(price)), special_denom=denom) - trigger_price = market.price_to_chain_format(human_readable_value=Decimal(str(0)), special_denom=denom) - quantity = market.quantity_to_chain_format(human_readable_value=Decimal(str(quantity)), special_denom=denom) + trigger_price = trigger_price or Decimal(0) + chain_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price) - if kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY + return self._basic_derivative_order( + market_id=market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + chain_price=chain_price, + chain_quantity=chain_quantity, + chain_margin=chain_margin, + order_type=order_type, + cid=cid, + chain_trigger_price=chain_trigger_price, + ) - elif not kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL + def binary_options_order( + self, + market_id: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + denom: Optional[Denom] = None, + ) -> injective_exchange_pb.DerivativeOrder: + market = self.binary_option_markets[market_id] - elif kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY_PO + chain_quantity = market.quantity_to_chain_format(human_readable_value=quantity, special_denom=denom) + chain_price = market.price_to_chain_format(human_readable_value=price, special_denom=denom) + chain_margin = market.margin_to_chain_format(human_readable_value=margin, special_denom=denom) - elif not kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL_PO + trigger_price = trigger_price or Decimal(0) + chain_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price, special_denom=denom) - return injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.DerivativeOrder( - market_id=market_id, - order_info=injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderInfo( - subaccount_id=subaccount_id, - fee_recipient=fee_recipient, - price=str(int(price)), - quantity=str(int(quantity)), - cid=cid, - ), - margin=str(int(margin)), + return self._basic_derivative_order( + market_id=market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + chain_price=chain_price, + chain_quantity=chain_quantity, + chain_margin=chain_margin, order_type=order_type, - trigger_price=str(int(trigger_price)), + cid=cid, + chain_trigger_price=chain_trigger_price, + ) + + # region Auction module + def MsgBid(self, sender: str, bid_amount: float, round: float): + be_amount = Decimal(str(bid_amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_auction_tx_pb.MsgBid( + sender=sender, + round=round, + bid_amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), + ) + + # endregion + + # region Authz module + def MsgGrantGeneric(self, granter: str, grantee: str, msg_type: str, expire_in: int): + auth = cosmos_authz_pb.GenericAuthorization(msg=msg_type) + any_auth = any_pb2.Any() + any_auth.Pack(auth, type_url_prefix="") + + grant = cosmos_authz_pb.Grant( + authorization=any_auth, + expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), + ) + + return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + + def MsgExec(self, grantee: str, msgs: List): + any_msgs: List[any_pb2.Any] = [] + for msg in msgs: + any_msg = any_pb2.Any() + any_msg.Pack(msg, type_url_prefix="") + any_msgs.append(any_msg) + + return cosmos_authz_tx_pb.MsgExec(grantee=grantee, msgs=any_msgs) + + def MsgRevoke(self, granter: str, grantee: str, msg_type: str): + return cosmos_authz_tx_pb.MsgRevoke(granter=granter, grantee=grantee, msg_type_url=msg_type) + + def msg_execute_contract_compat(self, sender: str, contract: str, msg: str, funds: str): + return wasmx_tx_pb.MsgExecuteContractCompat( + sender=sender, + contract=contract, + msg=msg, + funds=funds, ) + # endregion + + # region Bank module def MsgSend(self, from_address: str, to_address: str, amount: float, denom: str): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return cosmos_bank_tx_pb.MsgSend( from_address=from_address, to_address=to_address, - amount=[self.Coin(amount=int(be_amount), denom=token.denom)], + amount=[coin], ) - def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): - return wasm_tx_pb.MsgExecuteContract( + # endregion + + # region Chain Exchange module + def MsgDeposit(self, sender: str, subaccount_id: str, amount: float, denom: str): + """ + This method is deprecated and will be removed soon. Please use `msg_deposit` instead + """ + warn("This method is deprecated. Use msg_deposit instead", DeprecationWarning, stacklevel=2) + coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + + return injective_exchange_tx_pb.MsgDeposit( sender=sender, - contract=contract, - msg=bytes(msg, "utf-8"), - funds=kwargs.get("funds") # funds is a list of cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin. - # The coins in the list must be sorted in alphabetical order by denoms. + subaccount_id=subaccount_id, + amount=coin, ) - def MsgDeposit(self, sender: str, subaccount_id: str, amount: float, denom: str): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + def msg_deposit(self, sender: str, subaccount_id: str, amount: Decimal, denom: str): + coin = self.create_coin_amount(amount=amount, token_name=denom) return injective_exchange_tx_pb.MsgDeposit( sender=sender, subaccount_id=subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=coin, + ) + + def MsgWithdraw(self, sender: str, subaccount_id: str, amount: float, denom: str): + """ + This method is deprecated and will be removed soon. Please use `msg_withdraw` instead + """ + warn("This method is deprecated. Use msg_withdraw instead", DeprecationWarning, stacklevel=2) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + + return injective_exchange_tx_pb.MsgWithdraw( + sender=sender, + subaccount_id=subaccount_id, + amount=be_amount, + ) + + def msg_withdraw(self, sender: str, subaccount_id: str, amount: Decimal, denom: str): + be_amount = self.create_coin_amount(amount=amount, token_name=denom) + + return injective_exchange_tx_pb.MsgWithdraw( + sender=sender, + subaccount_id=subaccount_id, + amount=be_amount, + ) + + def msg_instant_spot_market_launch( + self, + sender: str, + ticker: str, + base_denom: str, + quote_denom: str, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantSpotMarketLaunch: + base_token = self.tokens[base_denom] + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals - base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal( + f"1e{base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + + return injective_exchange_tx_pb.MsgInstantSpotMarketLaunch( + sender=sender, + ticker=ticker, + base_denom=base_token.denom, + quote_denom=quote_token.denom, + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", + ) + + def msg_instant_perpetual_market_launch( + self, + sender: str, + ticker: str, + quote_denom: str, + oracle_base: str, + oracle_quote: str, + oracle_scale_factor: int, + oracle_type: str, + maker_fee_rate: Decimal, + taker_fee_rate: Decimal, + initial_margin_ratio: Decimal, + maintenance_margin_ratio: Decimal, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch: + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch( + sender=sender, + ticker=ticker, + quote_denom=quote_token.denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=injective_oracle_pb.OracleType.Value(oracle_type), + maker_fee_rate=f"{chain_maker_fee_rate.normalize():f}", + taker_fee_rate=f"{chain_taker_fee_rate.normalize():f}", + initial_margin_ratio=f"{chain_initial_margin_ratio.normalize():f}", + maintenance_margin_ratio=f"{chain_maintenance_margin_ratio.normalize():f}", + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", + ) + + def msg_instant_expiry_futures_market_launch( + self, + sender: str, + ticker: str, + quote_denom: str, + oracle_base: str, + oracle_quote: str, + oracle_scale_factor: int, + oracle_type: str, + expiry: int, + maker_fee_rate: Decimal, + taker_fee_rate: Decimal, + initial_margin_ratio: Decimal, + maintenance_margin_ratio: Decimal, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch: + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_exchange_tx_pb.MsgInstantExpiryFuturesMarketLaunch( + sender=sender, + ticker=ticker, + quote_denom=quote_token.denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=injective_oracle_pb.OracleType.Value(oracle_type), + expiry=expiry, + maker_fee_rate=f"{chain_maker_fee_rate.normalize():f}", + taker_fee_rate=f"{chain_taker_fee_rate.normalize():f}", + initial_margin_ratio=f"{chain_initial_margin_ratio.normalize():f}", + maintenance_margin_ratio=f"{chain_maintenance_margin_ratio.normalize():f}", + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", ) def MsgCreateSpotLimitOrder( @@ -370,67 +657,263 @@ def MsgCreateSpotLimitOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `msg_create_spot_limit_order` instead + """ + warn("This method is deprecated. Use msg_create_spot_limit_order instead", DeprecationWarning, stacklevel=2) + + order_type_name = "BUY" + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + return injective_exchange_tx_pb.MsgCreateSpotLimitOrder( sender=sender, - order=self.SpotOrder( + order=self.spot_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=price, - quantity=quantity, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + order_type=order_type_name, cid=cid, - **kwargs, ), ) - def MsgCreateSpotMarketOrder( + def msg_create_spot_limit_order( self, market_id: str, sender: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, - is_buy: bool, + price: Decimal, + quantity: Decimal, + order_type: str, cid: Optional[str] = None, - ): - return injective_exchange_tx_pb.MsgCreateSpotMarketOrder( + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateSpotLimitOrder: + return injective_exchange_tx_pb.MsgCreateSpotLimitOrder( sender=sender, - order=self.SpotOrder( + order=self.spot_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=price, quantity=quantity, - is_buy=is_buy, + order_type=order_type, cid=cid, + trigger_price=trigger_price, ), ) - def MsgCancelSpotOrder( + def MsgBatchCreateSpotLimitOrders(self, sender: str, orders: List): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_create_spot_limit_orders` instead + """ + warn( + "This method is deprecated. Use msg_batch_create_spot_limit_orders instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders(sender=sender, orders=orders) + + def msg_batch_create_spot_limit_orders( + self, sender: str, orders: List[injective_exchange_pb.SpotOrder] + ) -> injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders: + return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders(sender=sender, orders=orders) + + def MsgCreateSpotMarketOrder( self, market_id: str, sender: str, subaccount_id: str, - order_hash: Optional[str] = None, + fee_recipient: str, + price: float, + quantity: float, + is_buy: bool, cid: Optional[str] = None, ): - return injective_exchange_tx_pb.MsgCancelSpotOrder( - sender=sender, - market_id=market_id, - subaccount_id=subaccount_id, + """ + This method is deprecated and will be removed soon. Please use `msg_create_spot_market_order` instead + """ + warn("This method is deprecated. Use msg_create_spot_market_order instead", DeprecationWarning, stacklevel=2) + + order_type_name = "BUY" + if not is_buy: + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + return injective_exchange_tx_pb.MsgCreateSpotMarketOrder( + sender=sender, + order=self.spot_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + order_type=order_type_name, + cid=cid, + ), + ) + + def msg_create_spot_market_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateSpotMarketOrder: + return injective_exchange_tx_pb.MsgCreateSpotMarketOrder( + sender=sender, + order=self.spot_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ), + ) + + def MsgCancelSpotOrder( + self, + market_id: str, + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_cancel_spot_order` instead + """ + warn("This method is deprecated. Use msg_cancel_spot_order instead", DeprecationWarning, stacklevel=2) + return injective_exchange_tx_pb.MsgCancelSpotOrder( + sender=sender, + market_id=market_id, + subaccount_id=subaccount_id, order_hash=order_hash, cid=cid, ) - def MsgBatchCreateSpotLimitOrders(self, sender: str, orders: List): - return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders(sender=sender, orders=orders) + def msg_cancel_spot_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + ) -> injective_exchange_tx_pb.MsgCancelSpotOrder: + return injective_exchange_tx_pb.MsgCancelSpotOrder( + sender=sender, + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + ) def MsgBatchCancelSpotOrders(self, sender: str, data: List): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_cancel_spot_orders` instead + """ + warn("This method is deprecated. Use msg_batch_cancel_spot_orders instead", DeprecationWarning, stacklevel=2) return injective_exchange_tx_pb.MsgBatchCancelSpotOrders(sender=sender, data=data) - def MsgRewardsOptOut(self, sender: str): - return injective_exchange_tx_pb.MsgRewardsOptOut(sender=sender) + def msg_batch_cancel_spot_orders( + self, sender: str, orders_data: List[injective_exchange_tx_pb.OrderData] + ) -> injective_exchange_tx_pb.MsgBatchCancelSpotOrders: + return injective_exchange_tx_pb.MsgBatchCancelSpotOrders(sender=sender, data=orders_data) + + def MsgBatchUpdateOrders(self, sender: str, **kwargs): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_update_orders` instead + """ + warn("This method is deprecated. Use msg_batch_update_orders instead", DeprecationWarning, stacklevel=2) + return injective_exchange_tx_pb.MsgBatchUpdateOrders( + sender=sender, + subaccount_id=kwargs.get("subaccount_id"), + spot_market_ids_to_cancel_all=kwargs.get("spot_market_ids_to_cancel_all"), + derivative_market_ids_to_cancel_all=kwargs.get("derivative_market_ids_to_cancel_all"), + spot_orders_to_cancel=kwargs.get("spot_orders_to_cancel"), + derivative_orders_to_cancel=kwargs.get("derivative_orders_to_cancel"), + spot_orders_to_create=kwargs.get("spot_orders_to_create"), + derivative_orders_to_create=kwargs.get("derivative_orders_to_create"), + binary_options_orders_to_cancel=kwargs.get("binary_options_orders_to_cancel"), + binary_options_market_ids_to_cancel_all=kwargs.get("binary_options_market_ids_to_cancel_all"), + binary_options_orders_to_create=kwargs.get("binary_options_orders_to_create"), + ) + + def msg_batch_update_orders( + self, + sender: str, + subaccount_id: Optional[str] = None, + spot_market_ids_to_cancel_all: Optional[List[str]] = None, + derivative_market_ids_to_cancel_all: Optional[List[str]] = None, + spot_orders_to_cancel: Optional[List[injective_exchange_tx_pb.OrderData]] = None, + derivative_orders_to_cancel: Optional[List[injective_exchange_tx_pb.OrderData]] = None, + spot_orders_to_create: Optional[List[injective_exchange_pb.SpotOrder]] = None, + derivative_orders_to_create: Optional[List[injective_exchange_pb.DerivativeOrder]] = None, + binary_options_orders_to_cancel: Optional[List[injective_exchange_tx_pb.OrderData]] = None, + binary_options_market_ids_to_cancel_all: Optional[List[str]] = None, + binary_options_orders_to_create: Optional[List[injective_exchange_pb.DerivativeOrder]] = None, + ) -> injective_exchange_tx_pb.MsgBatchUpdateOrders: + return injective_exchange_tx_pb.MsgBatchUpdateOrders( + sender=sender, + subaccount_id=subaccount_id, + spot_market_ids_to_cancel_all=spot_market_ids_to_cancel_all, + derivative_market_ids_to_cancel_all=derivative_market_ids_to_cancel_all, + spot_orders_to_cancel=spot_orders_to_cancel, + derivative_orders_to_cancel=derivative_orders_to_cancel, + spot_orders_to_create=spot_orders_to_create, + derivative_orders_to_create=derivative_orders_to_create, + binary_options_orders_to_cancel=binary_options_orders_to_cancel, + binary_options_market_ids_to_cancel_all=binary_options_market_ids_to_cancel_all, + binary_options_orders_to_create=binary_options_orders_to_create, + ) + + def MsgPrivilegedExecuteContract( + self, sender: str, contract: str, msg: str, **kwargs + ) -> injective_exchange_tx_pb.MsgPrivilegedExecuteContract: + """ + This method is deprecated and will be removed soon. Please use `msg_privileged_execute_contract` instead + """ + warn("This method is deprecated. Use msg_privileged_execute_contract instead", DeprecationWarning, stacklevel=2) + + return injective_exchange_tx_pb.MsgPrivilegedExecuteContract( + sender=sender, + contract_address=contract, + data=msg, + funds=kwargs.get("funds") # funds is a string of Coin strings, comma separated, + # e.g. 100000inj,20000000000usdt + ) + + def msg_privileged_execute_contract( + self, + sender: str, + contract_address: str, + data: str, + funds: Optional[str] = None, + ) -> injective_exchange_tx_pb.MsgPrivilegedExecuteContract: + # funds is a string of Coin strings, comma separated, e.g. 100000inj,20000000000usdt + return injective_exchange_tx_pb.MsgPrivilegedExecuteContract( + sender=sender, + contract_address=contract_address, + data=data, + funds=funds, + ) def MsgCreateDerivativeLimitOrder( self, @@ -443,46 +926,105 @@ def MsgCreateDerivativeLimitOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `msg_create_derivative_limit_order` instead + """ + warn( + "This method is deprecated. Use msg_create_derivative_limit_order instead", DeprecationWarning, stacklevel=2 + ) + + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) / Decimal(str(kwargs["leverage"])) + + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + return injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder( sender=sender, - order=self.DerivativeOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=price, - quantity=quantity, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, ), ) - def MsgCreateDerivativeMarketOrder( + def msg_create_derivative_limit_order( self, market_id: str, sender: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, - is_buy: bool, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, cid: Optional[str] = None, - **kwargs, - ): - return injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder( + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder: + return injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder( sender=sender, - order=self.DerivativeOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=price, quantity=quantity, - is_buy=is_buy, + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=trigger_price, ), ) - def MsgCreateBinaryOptionsLimitOrder( + def MsgBatchCreateDerivativeLimitOrders(self, sender: str, orders: List): + """ + This method is deprecated and will be removed soon. + Please use `msg_batch_create_derivative_limit_orders` instead + """ + warn( + "This method is deprecated. Use msg_batch_create_derivative_limit_orders instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders(sender=sender, orders=orders) + + def msg_batch_create_derivative_limit_orders( + self, + sender: str, + orders: List[injective_exchange_pb.DerivativeOrder], + ) -> injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders: + return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders(sender=sender, orders=orders) + + def MsgCreateDerivativeMarketOrder( self, market_id: str, sender: str, @@ -493,95 +1035,156 @@ def MsgCreateBinaryOptionsLimitOrder( cid: Optional[str] = None, **kwargs, ): - return injective_exchange_tx_pb.MsgCreateBinaryOptionsLimitOrder( + """ + This method is deprecated and will be removed soon. Please use `msg_create_derivative_market_order` instead + """ + warn( + "This method is deprecated. Use msg_create_derivative_market_order instead", + DeprecationWarning, + stacklevel=2, + ) + + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) / Decimal(str(kwargs["leverage"])) + + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + + return injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder( sender=sender, - order=self.BinaryOptionsOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=price, - quantity=quantity, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, ), ) - def MsgCreateBinaryOptionsMarketOrder( + def msg_create_derivative_market_order( self, market_id: str, sender: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, cid: Optional[str] = None, - **kwargs, - ): - return injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder( + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder: + return injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder( sender=sender, - order=self.BinaryOptionsOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=price, quantity=quantity, + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=trigger_price, ), ) - def MsgCancelBinaryOptionsOrder( + def MsgCancelDerivativeOrder( self, - sender: str, market_id: str, + sender: str, subaccount_id: str, order_hash: Optional[str] = None, cid: Optional[str] = None, + **kwargs, ): - return injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder( + """ + This method is deprecated and will be removed soon. Please use `msg_cancel_derivative_order` instead + """ + warn( + "This method is deprecated. Use msg_cancel_derivative_order instead", + DeprecationWarning, + stacklevel=2, + ) + + is_conditional = kwargs.get("is_conditional", False) + is_buy = kwargs.get("order_direction", "buy") == "buy" + is_market_order = kwargs.get("order_type", "limit") == "market" + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) + + return injective_exchange_tx_pb.MsgCancelDerivativeOrder( sender=sender, market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash, + order_mask=order_mask, cid=cid, ) - def MsgAdminUpdateBinaryOptionsMarket( + def msg_cancel_derivative_order( self, - sender: str, market_id: str, - status: str, - **kwargs, - ): - price_to_bytes = None - - if kwargs.get("settlement_price") is not None: - scale_price = Decimal((kwargs.get("settlement_price") * pow(10, 18))) - price_to_bytes = bytes(str(scale_price), "utf-8") - - else: - price_to_bytes = "" + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + is_conditional: Optional[bool] = False, + is_buy: Optional[bool] = False, + is_market_order: Optional[bool] = False, + ) -> injective_exchange_tx_pb.MsgCancelDerivativeOrder: + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) - return injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket( + return injective_exchange_tx_pb.MsgCancelDerivativeOrder( sender=sender, market_id=market_id, - settlement_price=price_to_bytes, - expiration_timestamp=kwargs.get("expiration_timestamp"), - settlement_timestamp=kwargs.get("settlement_timestamp"), - status=status, + subaccount_id=subaccount_id, + order_hash=order_hash, + order_mask=order_mask, + cid=cid, ) - def MsgRelayProviderPrices(self, sender: str, provider: str, symbols: list, prices: list): - oracle_prices = [] - - for price in prices: - scale_price = Decimal((price) * pow(10, 18)) - price_to_bytes = bytes(str(scale_price), "utf-8") - oracle_prices.append(price_to_bytes) - - return injective_oracle_tx_pb.MsgRelayProviderPrices( - sender=sender, provider=provider, symbols=symbols, prices=oracle_prices + def MsgBatchCancelDerivativeOrders(self, sender: str, data: List): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_cancel_derivative_orders` instead + """ + warn( + "This method is deprecated. Use msg_batch_cancel_derivative_orders instead", + DeprecationWarning, + stacklevel=2, ) + return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders(sender=sender, data=data) + + def msg_batch_cancel_derivative_orders( + self, sender: str, orders_data: List[injective_exchange_tx_pb.OrderData] + ) -> injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders: + return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders(sender=sender, data=orders_data) def MsgInstantBinaryOptionsMarketLaunch( self, @@ -601,6 +1204,15 @@ def MsgInstantBinaryOptionsMarketLaunch( min_quantity_tick_size: float, **kwargs, ): + """ + This method is deprecated and will be removed soon. + Please use `msg_instant_binary_options_market_launch` instead + """ + warn( + "This method is deprecated. Use msg_instant_binary_options_market_launch instead", + DeprecationWarning, + stacklevel=2, + ) scaled_maker_fee_rate = Decimal((maker_fee_rate * pow(10, 18))) maker_fee_to_bytes = bytes(str(scaled_maker_fee_rate), "utf-8") @@ -630,75 +1242,281 @@ def MsgInstantBinaryOptionsMarketLaunch( admin=kwargs.get("admin"), ) - def MsgCancelDerivativeOrder( + def msg_instant_binary_options_market_launch( self, - market_id: str, sender: str, - subaccount_id: str, - order_hash: Optional[str] = None, - cid: Optional[str] = None, - **kwargs, - ): - order_mask = self.get_order_mask(**kwargs) - - return injective_exchange_tx_pb.MsgCancelDerivativeOrder( - sender=sender, - market_id=market_id, - subaccount_id=subaccount_id, - order_hash=order_hash, - order_mask=order_mask, - cid=cid, + ticker: str, + oracle_symbol: str, + oracle_provider: str, + oracle_type: str, + oracle_scale_factor: int, + maker_fee_rate: Decimal, + taker_fee_rate: Decimal, + expiration_timestamp: int, + settlement_timestamp: int, + admin: str, + quote_denom: str, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch: + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") - def MsgBatchCreateDerivativeLimitOrders(self, sender: str, orders: List): - return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders(sender=sender, orders=orders) + return injective_exchange_tx_pb.MsgInstantBinaryOptionsMarketLaunch( + sender=sender, + ticker=ticker, + oracle_symbol=oracle_symbol, + oracle_provider=oracle_provider, + oracle_type=injective_oracle_pb.OracleType.Value(oracle_type), + oracle_scale_factor=oracle_scale_factor, + maker_fee_rate=f"{chain_maker_fee_rate.normalize():f}", + taker_fee_rate=f"{chain_taker_fee_rate.normalize():f}", + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + admin=admin, + quote_denom=quote_token.denom, + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", + ) - def MsgBatchCancelDerivativeOrders(self, sender: str, data: List): - return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders(sender=sender, data=data) + def MsgCreateBinaryOptionsLimitOrder( + self, + market_id: str, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: float, + quantity: float, + cid: Optional[str] = None, + **kwargs, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_create_binary_options_limit_order` instead + """ + warn( + "This method is deprecated. Use msg_create_binary_options_limit_order instead", + DeprecationWarning, + stacklevel=2, + ) + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) - def MsgBatchUpdateOrders(self, sender: str, **kwargs): - return injective_exchange_tx_pb.MsgBatchUpdateOrders( + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + + return injective_exchange_tx_pb.MsgCreateBinaryOptionsLimitOrder( sender=sender, - subaccount_id=kwargs.get("subaccount_id"), - spot_market_ids_to_cancel_all=kwargs.get("spot_market_ids_to_cancel_all"), - derivative_market_ids_to_cancel_all=kwargs.get("derivative_market_ids_to_cancel_all"), - spot_orders_to_cancel=kwargs.get("spot_orders_to_cancel"), - derivative_orders_to_cancel=kwargs.get("derivative_orders_to_cancel"), - spot_orders_to_create=kwargs.get("spot_orders_to_create"), - derivative_orders_to_create=kwargs.get("derivative_orders_to_create"), - binary_options_orders_to_cancel=kwargs.get("binary_options_orders_to_cancel"), - binary_options_market_ids_to_cancel_all=kwargs.get("binary_options_market_ids_to_cancel_all"), - binary_options_orders_to_create=kwargs.get("binary_options_orders_to_create"), + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, + denom=kwargs.get("denom"), + ), ) - def MsgLiquidatePosition( + def msg_create_binary_options_limit_order( self, + market_id: str, sender: str, subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + denom: Optional[Denom] = None, + ) -> injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder: + return injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder( + sender=sender, + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + denom=denom, + ), + ) + + def MsgCreateBinaryOptionsMarketOrder( + self, market_id: str, - order: Optional[injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.DerivativeOrder] = None, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: float, + quantity: float, + cid: Optional[str] = None, + **kwargs, ): - return injective_exchange_tx_pb.MsgLiquidatePosition( - sender=sender, subaccount_id=subaccount_id, market_id=market_id, order=order + """ + This method is deprecated and will be removed soon. Please use `msg_create_binary_options_market_order` instead + """ + warn( + "This method is deprecated. Use msg_create_binary_options_market_order instead", + DeprecationWarning, + stacklevel=2, ) + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) - def MsgIncreasePositionMargin( + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + + return injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder( + sender=sender, + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, + denom=kwargs.get("denom"), + ), + ) + + def msg_create_binary_options_market_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + denom: Optional[Denom] = None, + ): + return injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder( + sender=sender, + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + denom=denom, + ), + ) + + def MsgCancelBinaryOptionsOrder( self, sender: str, - source_subaccount_id: str, - destination_subaccount_id: str, market_id: str, - amount: float, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, ): - market = self.derivative_markets[market_id] + """ + This method is deprecated and will be removed soon. Please use `msg_cancel_binary_options_order` instead + """ + warn( + "This method is deprecated. Use msg_cancel_binary_options_order instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder( + sender=sender, + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + ) - additional_margin = market.margin_to_chain_format(human_readable_value=Decimal(str(amount))) - return injective_exchange_tx_pb.MsgIncreasePositionMargin( + def msg_cancel_binary_options_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + is_conditional: Optional[bool] = False, + is_buy: Optional[bool] = False, + is_market_order: Optional[bool] = False, + ) -> injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder: + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) + + return injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder( sender=sender, - source_subaccount_id=source_subaccount_id, - destination_subaccount_id=destination_subaccount_id, market_id=market_id, - amount=str(int(additional_margin)), + subaccount_id=subaccount_id, + order_hash=order_hash, + order_mask=order_mask, + cid=cid, ) def MsgSubaccountTransfer( @@ -709,24 +1527,38 @@ def MsgSubaccountTransfer( amount: int, denom: str, ): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + """ + This method is deprecated and will be removed soon. Please use `msg_subaccount_transfer` instead + """ + warn( + "This method is deprecated. Use msg_subaccount_transfer instead", + DeprecationWarning, + stacklevel=2, + ) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgSubaccountTransfer( sender=sender, source_subaccount_id=source_subaccount_id, destination_subaccount_id=destination_subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=be_amount, ) - def MsgWithdraw(self, sender: str, subaccount_id: str, amount: float, denom: str): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + def msg_subaccount_transfer( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + amount: Decimal, + denom: str, + ) -> injective_exchange_tx_pb.MsgSubaccountTransfer: + be_amount = self.create_coin_amount(amount=amount, token_name=denom) - return injective_exchange_tx_pb.MsgWithdraw( + return injective_exchange_tx_pb.MsgSubaccountTransfer( sender=sender, - subaccount_id=subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=be_amount, ) def MsgExternalTransfer( @@ -737,140 +1569,201 @@ def MsgExternalTransfer( amount: int, denom: str, ): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + """ + This method is deprecated and will be removed soon. Please use `msg_external_transfer` instead + """ + warn( + "This method is deprecated. Use msg_external_transfer instead", + DeprecationWarning, + stacklevel=2, + ) + coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgExternalTransfer( sender=sender, source_subaccount_id=source_subaccount_id, destination_subaccount_id=destination_subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=coin, ) - def MsgBid(self, sender: str, bid_amount: float, round: float): - be_amount = Decimal(str(bid_amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + def msg_external_transfer( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + amount: Decimal, + denom: str, + ) -> injective_exchange_tx_pb.MsgExternalTransfer: + coin = self.create_coin_amount(amount=amount, token_name=denom) - return injective_auction_tx_pb.MsgBid( + return injective_exchange_tx_pb.MsgExternalTransfer( sender=sender, - round=round, - bid_amount=self.Coin(amount=int(be_amount), denom=INJ_DENOM), + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=coin, ) - def MsgGrantGeneric(self, granter: str, grantee: str, msg_type: str, expire_in: int): - auth = cosmos_authz_pb.GenericAuthorization(msg=msg_type) - any_auth = any_pb2.Any() - any_auth.Pack(auth, type_url_prefix="") - - grant = cosmos_authz_pb.Grant( - authorization=any_auth, - expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), + def MsgLiquidatePosition( + self, + sender: str, + subaccount_id: str, + market_id: str, + order: Optional[injective_exchange_pb.DerivativeOrder] = None, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_liquidate_position` instead + """ + warn( + "This method is deprecated. Use msg_liquidate_position instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgLiquidatePosition( + sender=sender, subaccount_id=subaccount_id, market_id=market_id, order=order ) - return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + def msg_liquidate_position( + self, + sender: str, + subaccount_id: str, + market_id: str, + order: Optional[injective_exchange_pb.DerivativeOrder] = None, + ) -> injective_exchange_tx_pb.MsgLiquidatePosition: + return injective_exchange_tx_pb.MsgLiquidatePosition( + sender=sender, subaccount_id=subaccount_id, market_id=market_id, order=order + ) - def MsgGrantTyped( + def msg_emergency_settle_market( self, - granter: str, - grantee: str, - msg_type: str, - expire_in: int, + sender: str, subaccount_id: str, - **kwargs, - ): - auth = None - if msg_type == "CreateSpotLimitOrderAuthz": - auth = injective_authz_pb.CreateSpotLimitOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CreateSpotMarketOrderAuthz": - auth = injective_authz_pb.CreateSpotMarketOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCreateSpotLimitOrdersAuthz": - auth = injective_authz_pb.BatchCreateSpotLimitOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CancelSpotOrderAuthz": - auth = injective_authz_pb.CancelSpotOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCancelSpotOrdersAuthz": - auth = injective_authz_pb.BatchCancelSpotOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CreateDerivativeLimitOrderAuthz": - auth = injective_authz_pb.CreateDerivativeLimitOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CreateDerivativeMarketOrderAuthz": - auth = injective_authz_pb.CreateDerivativeMarketOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCreateDerivativeLimitOrdersAuthz": - auth = injective_authz_pb.BatchCreateDerivativeLimitOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CancelDerivativeOrderAuthz": - auth = injective_authz_pb.CancelDerivativeOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCancelDerivativeOrdersAuthz": - auth = injective_authz_pb.BatchCancelDerivativeOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchUpdateOrdersAuthz": - auth = injective_authz_pb.BatchUpdateOrdersAuthz( - subaccount_id=subaccount_id, - spot_markets=kwargs.get("spot_markets"), - derivative_markets=kwargs.get("derivative_markets"), - ) + market_id: str, + ) -> injective_exchange_tx_pb.MsgEmergencySettleMarket: + return injective_exchange_tx_pb.MsgEmergencySettleMarket( + sender=sender, subaccount_id=subaccount_id, market_id=market_id + ) - any_auth = any_pb2.Any() - any_auth.Pack(auth, type_url_prefix="") + def MsgIncreasePositionMargin( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + market_id: str, + amount: float, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_increase_position_margin` instead + """ + warn( + "This method is deprecated. Use msg_increase_position_margin instead", + DeprecationWarning, + stacklevel=2, + ) + market = self.derivative_markets[market_id] - grant = cosmos_authz_pb.Grant( - authorization=any_auth, - expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), + additional_margin = market.margin_to_chain_format(human_readable_value=Decimal(str(amount))) + return injective_exchange_tx_pb.MsgIncreasePositionMargin( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + market_id=market_id, + amount=str(int(additional_margin)), ) - return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + def msg_increase_position_margin( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + market_id: str, + amount: Decimal, + ): + market = self.derivative_markets[market_id] - def MsgExec(self, grantee: str, msgs: List): - any_msgs: List[any_pb2.Any] = [] - for msg in msgs: - any_msg = any_pb2.Any() - any_msg.Pack(msg, type_url_prefix="") - any_msgs.append(any_msg) + additional_margin = market.margin_to_chain_format(human_readable_value=amount) + return injective_exchange_tx_pb.MsgIncreasePositionMargin( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + market_id=market_id, + amount=str(int(additional_margin)), + ) + + def MsgRewardsOptOut(self, sender: str): + """ + This method is deprecated and will be removed soon. Please use `msg_rewards_opt_out` instead + """ + warn( + "This method is deprecated. Use msg_rewards_opt_out instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgRewardsOptOut(sender=sender) - return cosmos_authz_tx_pb.MsgExec(grantee=grantee, msgs=any_msgs) + def msg_rewards_opt_out(self, sender: str) -> injective_exchange_tx_pb.MsgRewardsOptOut: + return injective_exchange_tx_pb.MsgRewardsOptOut(sender=sender) - def MsgRevoke(self, granter: str, grantee: str, msg_type: str): - return cosmos_authz_tx_pb.MsgRevoke(granter=granter, grantee=grantee, msg_type_url=msg_type) + def MsgAdminUpdateBinaryOptionsMarket( + self, + sender: str, + market_id: str, + status: str, + **kwargs, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_admin_update_binary_options_market` instead + """ + warn( + "This method is deprecated. Use msg_admin_update_binary_options_market instead", + DeprecationWarning, + stacklevel=2, + ) - def MsgRelayPriceFeedPrice(self, sender: list, base: list, quote: list, price: list): - return injective_oracle_tx_pb.MsgRelayPriceFeedPrice(sender=sender, base=base, quote=quote, price=price) + if kwargs.get("settlement_price") is not None: + scale_price = Decimal((kwargs.get("settlement_price") * pow(10, 18))) + price_to_bytes = bytes(str(scale_price), "utf-8") - def MsgSendToEth(self, denom: str, sender: str, eth_dest: str, amount: float, bridge_fee: float): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) - be_bridge_fee = token.chain_formatted_value(human_readable_value=Decimal(str(bridge_fee))) + else: + price_to_bytes = "" - return injective_peggy_tx_pb.MsgSendToEth( + return injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket( sender=sender, - eth_dest=eth_dest, - amount=self.Coin(amount=int(be_amount), denom=token.denom), - bridge_fee=self.Coin(amount=int(be_bridge_fee), denom=token.denom), + market_id=market_id, + settlement_price=price_to_bytes, + expiration_timestamp=kwargs.get("expiration_timestamp"), + settlement_timestamp=kwargs.get("settlement_timestamp"), + status=status, ) - def MsgDelegate(self, delegator_address: str, validator_address: str, amount: float): - be_amount = Decimal(str(amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + def msg_admin_update_binary_options_market( + self, + sender: str, + market_id: str, + status: str, + settlement_price: Optional[Decimal] = None, + expiration_timestamp: Optional[int] = None, + settlement_timestamp: Optional[int] = None, + ) -> injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket: + market = self.binary_option_markets[market_id] - return cosmos_staking_tx_pb.MsgDelegate( - delegator_address=delegator_address, - validator_address=validator_address, - amount=self.Coin(amount=int(be_amount), denom=INJ_DENOM), + if settlement_price is not None: + chain_settlement_price = market.price_to_chain_format(human_readable_value=settlement_price) + price_parameter = f"{chain_settlement_price.normalize():f}" + else: + price_parameter = None + + return injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket( + sender=sender, + market_id=market_id, + settlement_price=price_parameter, + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + status=status, ) + # endregion + + # region Insurance module def MsgCreateInsuranceFund( self, sender: str, @@ -883,7 +1776,7 @@ def MsgCreateInsuranceFund( initial_deposit: int, ): token = self.tokens[quote_denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(initial_deposit))) + deposit = self.create_coin_amount(Decimal(str(initial_deposit)), quote_denom) return injective_insurance_tx_pb.MsgCreateInsuranceFund( sender=sender, @@ -893,7 +1786,7 @@ def MsgCreateInsuranceFund( oracle_quote=oracle_quote, oracle_type=oracle_type, expiry=expiry, - initial_deposit=self.Coin(amount=int(be_amount), denom=token.denom), + initial_deposit=deposit, ) def MsgUnderwrite( @@ -903,13 +1796,12 @@ def MsgUnderwrite( quote_denom: str, amount: int, ): - token = self.tokens[quote_denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=quote_denom) return injective_insurance_tx_pb.MsgUnderwrite( sender=sender, market_id=market_id, - deposit=self.Coin(amount=int(be_amount), denom=token.denom), + deposit=be_amount, ) def MsgRequestRedemption( @@ -922,49 +1814,56 @@ def MsgRequestRedemption( return injective_insurance_tx_pb.MsgRequestRedemption( sender=sender, market_id=market_id, - amount=self.Coin(amount=amount, denom=share_denom), + amount=self.coin(amount=amount, denom=share_denom), ) - def MsgWithdrawDelegatorReward(self, delegator_address: str, validator_address: str): - return cosmos_distribution_tx_pb.MsgWithdrawDelegatorReward( - delegator_address=delegator_address, validator_address=validator_address + # endregion + + # region Oracle module + def MsgRelayProviderPrices(self, sender: str, provider: str, symbols: list, prices: list): + oracle_prices = [] + + for price in prices: + scale_price = Decimal((price) * pow(10, 18)) + price_to_bytes = bytes(str(scale_price), "utf-8") + oracle_prices.append(price_to_bytes) + + return injective_oracle_tx_pb.MsgRelayProviderPrices( + sender=sender, provider=provider, symbols=symbols, prices=oracle_prices ) - def MsgWithdrawValidatorCommission(self, validator_address: str): - return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) + def MsgRelayPriceFeedPrice(self, sender: list, base: list, quote: list, price: list): + return injective_oracle_tx_pb.MsgRelayPriceFeedPrice(sender=sender, base=base, quote=quote, price=price) - def MsgVote( - self, - proposal_id: str, - voter: str, - option: int, - ): - return cosmos_gov_tx_pb.MsgVote(proposal_id=proposal_id, voter=voter, option=option) + # endregion - def MsgPrivilegedExecuteContract( - self, sender: str, contract: str, msg: str, **kwargs - ) -> injective_exchange_tx_pb.MsgPrivilegedExecuteContract: - return injective_exchange_tx_pb.MsgPrivilegedExecuteContract( + # region Peggy module + def MsgSendToEth(self, denom: str, sender: str, eth_dest: str, amount: float, bridge_fee: float): + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + be_bridge_fee = self.create_coin_amount(amount=Decimal(str(bridge_fee)), token_name=denom) + + return injective_peggy_tx_pb.MsgSendToEth( sender=sender, - contract_address=contract, - data=msg, - funds=kwargs.get("funds") # funds is a string of Coin strings, comma separated, - # e.g. 100000inj,20000000000usdt + eth_dest=eth_dest, + amount=be_amount, + bridge_fee=be_bridge_fee, ) - def MsgInstantiateContract( - self, sender: str, admin: str, code_id: int, label: str, message: bytes, **kwargs - ) -> wasm_tx_pb.MsgInstantiateContract: - return wasm_tx_pb.MsgInstantiateContract( - sender=sender, - admin=admin, - code_id=code_id, - label=label, - msg=message, - funds=kwargs.get("funds"), # funds is a list of cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin. - # The coins in the list must be sorted in alphabetical order by denoms. + # endregion + + # region Staking module + def MsgDelegate(self, delegator_address: str, validator_address: str, amount: float): + be_amount = Decimal(str(amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return cosmos_staking_tx_pb.MsgDelegate( + delegator_address=delegator_address, + validator_address=validator_address, + amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), ) + # endregion + + # region Tokenfactory module def msg_create_denom( self, sender: str, @@ -982,14 +1881,14 @@ def msg_create_denom( def msg_mint( self, sender: str, - amount: cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin, + amount: base_coin_pb.Coin, ) -> token_factory_tx_pb.MsgMint: return token_factory_tx_pb.MsgMint(sender=sender, amount=amount) def msg_burn( self, sender: str, - amount: cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin, + amount: base_coin_pb.Coin, ) -> token_factory_tx_pb.MsgBurn: return token_factory_tx_pb.MsgBurn(sender=sender, amount=amount) @@ -1039,14 +1938,108 @@ def msg_change_admin( new_admin=new_admin, ) - def msg_execute_contract_compat(self, sender: str, contract: str, msg: str, funds: str): - return wasmx_tx_pb.MsgExecuteContractCompat( + # endregion + + # region Wasm module + def MsgInstantiateContract( + self, sender: str, admin: str, code_id: int, label: str, message: bytes, **kwargs + ) -> wasm_tx_pb.MsgInstantiateContract: + return wasm_tx_pb.MsgInstantiateContract( + sender=sender, + admin=admin, + code_id=code_id, + label=label, + msg=message, + funds=kwargs.get("funds"), # funds is a list of base_coin_pb.Coin. + # The coins in the list must be sorted in alphabetical order by denoms. + ) + + def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): + return wasm_tx_pb.MsgExecuteContract( sender=sender, contract=contract, - msg=msg, - funds=funds, + msg=bytes(msg, "utf-8"), + funds=kwargs.get("funds") # funds is a list of base_coin_pb.Coin. + # The coins in the list must be sorted in alphabetical order by denoms. + ) + + # endregion + + def MsgGrantTyped( + self, + granter: str, + grantee: str, + msg_type: str, + expire_in: int, + subaccount_id: str, + **kwargs, + ): + auth = None + if msg_type == "CreateSpotLimitOrderAuthz": + auth = injective_authz_pb.CreateSpotLimitOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CreateSpotMarketOrderAuthz": + auth = injective_authz_pb.CreateSpotMarketOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCreateSpotLimitOrdersAuthz": + auth = injective_authz_pb.BatchCreateSpotLimitOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CancelSpotOrderAuthz": + auth = injective_authz_pb.CancelSpotOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCancelSpotOrdersAuthz": + auth = injective_authz_pb.BatchCancelSpotOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CreateDerivativeLimitOrderAuthz": + auth = injective_authz_pb.CreateDerivativeLimitOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CreateDerivativeMarketOrderAuthz": + auth = injective_authz_pb.CreateDerivativeMarketOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCreateDerivativeLimitOrdersAuthz": + auth = injective_authz_pb.BatchCreateDerivativeLimitOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CancelDerivativeOrderAuthz": + auth = injective_authz_pb.CancelDerivativeOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCancelDerivativeOrdersAuthz": + auth = injective_authz_pb.BatchCancelDerivativeOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchUpdateOrdersAuthz": + auth = injective_authz_pb.BatchUpdateOrdersAuthz( + subaccount_id=subaccount_id, + spot_markets=kwargs.get("spot_markets"), + derivative_markets=kwargs.get("derivative_markets"), + ) + + any_auth = any_pb2.Any() + any_auth.Pack(auth, type_url_prefix="") + + grant = cosmos_authz_pb.Grant( + authorization=any_auth, + expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), ) + return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + + def MsgVote( + self, + proposal_id: str, + voter: str, + option: int, + ): + return cosmos_gov_tx_pb.MsgVote(proposal_id=proposal_id, voter=voter, option=option) + def chain_stream_bank_balances_filter( self, accounts: Optional[List[str]] = None ) -> chain_stream_query.BankBalancesFilter: @@ -1101,6 +2094,54 @@ def chain_stream_oracle_price_filter( symbols = symbols or ["*"] return chain_stream_query.OraclePriceFilter(symbol=symbols) + # ------------------------------------------------ + # Distribution module's messages + + def msg_set_withdraw_address(self, delegator_address: str, withdraw_address: str): + return cosmos_distribution_tx_pb.MsgSetWithdrawAddress( + delegator_address=delegator_address, withdraw_address=withdraw_address + ) + + # Deprecated + def MsgWithdrawDelegatorReward(self, delegator_address: str, validator_address: str): + """ + This method is deprecated and will be removed soon. Please use `msg_withdraw_delegator_reward` instead + """ + warn("This method is deprecated. Use msg_withdraw_delegator_reward instead", DeprecationWarning, stacklevel=2) + return cosmos_distribution_tx_pb.MsgWithdrawDelegatorReward( + delegator_address=delegator_address, validator_address=validator_address + ) + + def msg_withdraw_delegator_reward(self, delegator_address: str, validator_address: str): + return cosmos_distribution_tx_pb.MsgWithdrawDelegatorReward( + delegator_address=delegator_address, validator_address=validator_address + ) + + def MsgWithdrawValidatorCommission(self, validator_address: str): + """ + This method is deprecated and will be removed soon. Please use `msg_withdraw_validator_commission` instead + """ + warn( + "This method is deprecated. Use msg_withdraw_validator_commission instead", DeprecationWarning, stacklevel=2 + ) + return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) + + def msg_withdraw_validator_commission(self, validator_address: str): + return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) + + def msg_fund_community_pool(self, amounts: List[base_coin_pb.Coin], depositor: str): + return cosmos_distribution_tx_pb.MsgFundCommunityPool(amount=amounts, depositor=depositor) + + def msg_update_distribution_params(self, authority: str, community_tax: str, withdraw_address_enabled: bool): + params = cosmos_distribution_pb2.Params( + community_tax=community_tax, + withdraw_addr_enabled=withdraw_address_enabled, + ) + return cosmos_distribution_tx_pb.MsgUpdateParams(authority=authority, params=params) + + def msg_community_pool_spend(self, authority: str, recipient: str, amount: List[base_coin_pb.Coin]): + return cosmos_distribution_tx_pb.MsgCommunityPoolSpend(authority=authority, recipient=recipient, amount=amount) + # data field format: [request-msg-header][raw-byte-msg-response] # you need to figure out this magic prefix number to trim request-msg-header off the data # this method handles only exchange responses @@ -1311,3 +2352,61 @@ def _initialize_markets_and_tokens_from_files(self): self.spot_markets = spot_markets self.derivative_markets = derivative_markets self.binary_option_markets = dict() + + def _order_mask(self, is_conditional: bool, is_buy: bool, is_market_order: bool) -> int: + order_mask = 0 + + if is_conditional: + order_mask += injective_exchange_pb.OrderMask.CONDITIONAL + else: + order_mask += injective_exchange_pb.OrderMask.REGULAR + + if is_buy: + order_mask += injective_exchange_pb.OrderMask.DIRECTION_BUY_OR_HIGHER + else: + order_mask += injective_exchange_pb.OrderMask.DIRECTION_SELL_OR_LOWER + + if is_market_order: + order_mask += injective_exchange_pb.OrderMask.TYPE_MARKET + else: + order_mask += injective_exchange_pb.OrderMask.TYPE_LIMIT + + if order_mask == 0: + order_mask = 1 + + return order_mask + + def _basic_derivative_order( + self, + market_id: str, + subaccount_id: str, + fee_recipient: str, + chain_price: Decimal, + chain_quantity: Decimal, + chain_margin: Decimal, + order_type: str, + cid: Optional[str] = None, + chain_trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_pb.DerivativeOrder: + formatted_quantity = f"{chain_quantity.normalize():f}" + formatted_price = f"{chain_price.normalize():f}" + formatted_margin = f"{chain_margin.normalize():f}" + + trigger_price = chain_trigger_price or Decimal(0) + formatted_trigger_price = f"{trigger_price.normalize():f}" + + chain_order_type = injective_exchange_pb.OrderType.Value(order_type) + + return injective_exchange_pb.DerivativeOrder( + market_id=market_id, + order_info=injective_exchange_pb.OrderInfo( + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=formatted_price, + quantity=formatted_quantity, + cid=cid, + ), + order_type=chain_order_type, + margin=formatted_margin, + trigger_price=formatted_trigger_price, + ) diff --git a/pyinjective/core/broadcaster.py b/pyinjective/core/broadcaster.py index 22df562b..f279baea 100644 --- a/pyinjective/core/broadcaster.py +++ b/pyinjective/core/broadcaster.py @@ -264,7 +264,7 @@ async def configure_gas_fee_for_transaction( gas_limit = math.ceil(Decimal(str(sim_res["gasInfo"]["gasUsed"])) * self._gas_limit_adjustment_multiplier) fee = [ - self._composer.Coin( + self._composer.coin( amount=self._gas_price * gas_limit, denom=self._client.network.fee_denom, ) @@ -292,7 +292,7 @@ async def configure_gas_fee_for_transaction( transaction_gas_limit = messages_gas_limit + self.TRANSACTION_GAS_LIMIT fee = [ - self._composer.Coin( + self._composer.coin( amount=math.ceil(self._gas_price * transaction_gas_limit), denom=self._client.network.fee_denom, ) diff --git a/pyinjective/core/market.py b/pyinjective/core/market.py index 2bd4fe1b..66063130 100644 --- a/pyinjective/core/market.py +++ b/pyinjective/core/market.py @@ -169,6 +169,17 @@ def price_to_chain_format(self, human_readable_value: Decimal, special_denom: Op return extended_chain_formatted_value + def margin_to_chain_format(self, human_readable_value: Decimal, special_denom: Optional[Denom] = None) -> Decimal: + decimals = self.quote_token.decimals if special_denom is None else special_denom.quote + min_quantity_tick_size = ( + self.min_quantity_tick_size if special_denom is None else special_denom.min_quantity_tick_size + ) + chain_formatted_value = human_readable_value * Decimal(f"1e{decimals}") + quantized_value = (chain_formatted_value // min_quantity_tick_size) * min_quantity_tick_size + extended_chain_formatted_value = quantized_value * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return extended_chain_formatted_value + def calculate_margin_in_chain_format( self, human_readable_quantity: Decimal, diff --git a/pyinjective/denoms_devnet.ini b/pyinjective/denoms_devnet.ini index 62979d72..2b6020db 100644 --- a/pyinjective/denoms_devnet.ini +++ b/pyinjective/denoms_devnet.ini @@ -164,10 +164,37 @@ min_display_quantity_tick_size = 0.00001 description = 'Devnet Spot PROJ/INJ' base = 18 quote = 18 -min_price_tick_size = 0.001 -min_display_price_tick_size = 0.001 -min_quantity_tick_size = 10000000000000 -min_display_quantity_tick_size = 0.00001 +min_price_tick_size = 0.00000001 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000000000000000 +min_display_quantity_tick_size = 1000 + +[0x2d3b8d8833dda54a717adea9119134556848105fd6028e9a4a526e4e5a122a57] +description = 'Devnet Spot KIRA/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000 +min_display_quantity_tick_size = 1000 + +[0x42edf70cc37e155e9b9f178e04e18999bc8c404bd7b638cc4cbf41da8ef45a21] +description = 'Devnet Spot QUNT/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000 +min_display_quantity_tick_size = 1000 + +[0xc8fafa1fcab27e16da20e98b4dc9dda45320418c27db80663b21edac72f3b597] +description = 'Devnet Spot HDRO/INJ' +base = 6 +quote = 18 +min_price_tick_size = 1000000 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 1000000 +min_display_quantity_tick_size = 1 [0x1422a13427d5eabd4d8de7907c8340f7e58cb15553a9fd4ad5c90406561886f9] description = 'Devnet Derivative COMP/USDT PERP' @@ -287,10 +314,18 @@ decimals = 18 peggy_denom = peggy0xAaEf88cEa01475125522e117BFe45cF32044E238 decimals = 18 +[HDRO] +peggy_denom = factory/inj1etz0laas6h7vemg3qtd67jpr6lh8v7xz7gfzqw/hdro +decimals = 6 + [INJ] peggy_denom = inj decimals = 18 +[KIRA] +peggy_denom = factory/inj1xy3kvlr4q4wdd6lrelsrw2fk2ged0any44hhwq/KIRA +decimals = 6 + [LINK] peggy_denom = peggy0x514910771AF9Ca656af840dff83E8264EcF986CA decimals = 18 @@ -303,6 +338,10 @@ decimals = 18 peggy_denom = proj decimals = 18 +[QUNT] +peggy_denom = factory/inj127l5a2wmkyvucxdlupqyac3y0v6wqfhq03ka64/qunt +decimals = 6 + [SOMM] peggy_denom = ibc/34346A60A95EB030D62D6F5BDD4B745BE18E8A693372A8A347D5D53DBBB1328B decimals = 6 diff --git a/pyinjective/denoms_mainnet.ini b/pyinjective/denoms_mainnet.ini index b2430837..5f6611ef 100644 --- a/pyinjective/denoms_mainnet.ini +++ b/pyinjective/denoms_mainnet.ini @@ -682,6 +682,105 @@ min_display_price_tick_size = 0.000001 min_quantity_tick_size = 10000000000000000000 min_display_quantity_tick_size = 10 +[0xe6dd9895b169e2ca0087fcb8e8013805d06c3ed8ffc01ccaa31c710eef14a984] +description = 'Mainnet Spot DOJO/INJ' +base = 18 +quote = 18 +min_price_tick_size = 0.000001 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 10000000000000000000 +min_display_quantity_tick_size = 10 + +[0x0a1366c8b05658c0ccca6064e4b20aacd5ad350c02debd6ec0f4dc9178145d14] +description = 'Mainnet Spot GYEN/USDT' +base = 6 +quote = 6 +min_price_tick_size = 0.000001 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 100000000 +min_display_quantity_tick_size = 100 + +[0x9c8a91a894f773792b1e8d0b6a8224a6b748753738e9945020ee566266f817be] +description = 'Mainnet Spot USDCnb/USDT' +base = 6 +quote = 6 +min_price_tick_size = 0.0001 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 100000 +min_display_quantity_tick_size = 0.1 + +[0x9c42d763ba5135809ac4684b02082e9c880d69f6b96d258fe4c172396e9af7be] +description = 'Mainnet Spot ANDR/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000000 +min_display_price_tick_size = 0.00001 +min_quantity_tick_size = 100000 +min_display_quantity_tick_size = 0.1 + +[0x1b1e062b3306f26ae3af3c354a10c1cf38b00dcb42917f038ba3fc14978b1dd8] +description = 'Mainnet Spot hINJ/INJ' +base = 18 +quote = 18 +min_price_tick_size = 0.0001 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1000000000000000 +min_display_quantity_tick_size = 0.001 + +[0x959c9401a557ac090fff3ec11db5a1a9832e51a97a41b722d2496bb3cb0b2f72] +description = 'Mainnet Spot ANDR/INJ' +base = 6 +quote = 6 +min_price_tick_size = 0.0001 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1000000 +min_display_quantity_tick_size = 1 + +[0x697457537bc2af5ff652bc0616fe23537437a570d0e4d91566f03af279e095d5] +description = 'Mainnet Spot PHUC/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000 +min_display_quantity_tick_size = 1000 + +[0x42edf70cc37e155e9b9f178e04e18999bc8c404bd7b638cc4cbf41da8ef45a21] +description = 'Mainnet Spot QUNT/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000 +min_display_quantity_tick_size = 1000 + +[0x586409ac5f6d6e90a81d2585b9a8e76de0b4898d5f2c047d0bc025a036489ba1] +description = 'Mainnet Spot WHALE/INJ' +base = 6 +quote = 18 +min_price_tick_size = 1000000 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 1000000 +min_display_quantity_tick_size = 1 + +[0xc8fafa1fcab27e16da20e98b4dc9dda45320418c27db80663b21edac72f3b597] +description = 'Mainnet Spot HDRO/INJ' +base = 6 +quote = 18 +min_price_tick_size = 1000000 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 1000000 +min_display_quantity_tick_size = 1 + +[0xb965ebede42e67af153929339040e650d5c2af26d6aa43382c110d943c627b0a] +description = 'Mainnet Spot PYTH/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000000 +min_display_price_tick_size = 0.00001 +min_quantity_tick_size = 100000 +min_display_quantity_tick_size = 0.1 + [0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce] description = 'Mainnet Derivative BTC/USDT PERP' base = 0 @@ -736,14 +835,32 @@ min_display_price_tick_size = 0.001 min_quantity_tick_size = 0.01 min_display_quantity_tick_size = 0.01 +[0xcf18525b53e54ad7d27477426ade06d69d8d56d2f3bf35fe5ce2ad9eb97c2fbc] +description = 'Mainnet Derivative OSMO/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + [0x06c5a306492ddc2b8dc56969766959163287ed68a6b59baa2f42330dda0aebe0] description = 'Mainnet Derivative SOL/USDT PERP' base = 0 quote = 6 min_price_tick_size = 10000 min_display_price_tick_size = 0.01 -min_quantity_tick_size = 0.1 -min_display_quantity_tick_size = 0.1 +min_quantity_tick_size = 0.001 +min_display_quantity_tick_size = 0.001 + +[0x3b7fb1d9351f7fa2e6e0e5a11b3639ee5e0486c33a6a74f629c3fc3c3043efd5] +description = 'Mainnet Derivative BONK/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 0.01 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 10000 +min_display_quantity_tick_size = 10000 [0xcd0c859a99f26bb3530e21890937ed77d20754aa7825a599c71710514fc125ef] description = 'Mainnet Derivative 1MPEPE/USDT PERP' @@ -817,10 +934,86 @@ min_display_price_tick_size = 0.00001 min_quantity_tick_size = 1 min_display_quantity_tick_size = 1 +[0x30a1463cfb4c393c80e257ab93118cecd73c1e632dc4d2d31c12a51bc0a70bd7] +description = 'Mainnet Derivative AVAX/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.01 +min_quantity_tick_size = 0.01 +min_display_quantity_tick_size = 0.01 + +[0x18b2ca44b3d20a3b87c87d3765669b09b73b5e900693896c08394c70e79ab1e7] +description = 'Mainnet Derivative SUI/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + +[0x1a6d3a59f45904e0a4a2eed269fc2f552e7e407ac90aaaeb602c31b017573f88] +description = 'Mainnet Derivative WIF/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 100 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1 +min_display_quantity_tick_size = 1 + +[0x48fcecd66ebabbf5a331178ec693b261dfae66ddfe6f552d7446744c6e78046c] +description = 'Mainnet Derivative OP/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + +[0x6ddf0b8fbbd888981aafdae9fc967a12c6777aac4dd100a8257b8755c0c4b7d5] +description = 'Mainnet Derivative ARB/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + +[0xf1bc70398e9b469db459f3153433c6bd1253bd02377248ee29bd346a218e6243] +description = 'Mainnet Derivative W/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 100 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1 +min_display_quantity_tick_size = 1 + +[0x03c8da1f6aaf8aca2be26b0f4d6b89d475835c7812a1dcdb19af7dec1c6b7f60] +description = 'Mainnet Derivative LINK/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.01 +min_quantity_tick_size = 0.01 +min_display_quantity_tick_size = 0.01 + +[0x7980993e508e0efc1c2634c153a1ef90f517b74351d6406221c77c04ec4799fe] +description = 'Mainnet Derivative DOGE/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 10 +min_display_price_tick_size = 0.00001 +min_quantity_tick_size = 10 +min_display_quantity_tick_size = 10 + [AAVE] peggy_denom = peggy0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9 decimals = 18 +[ANDR] +peggy_denom = ibc/61FA42C3F0B0F8768ED2CE380EDD3BE0E4CB7E67688F81F70DE9ECF5F8684E1E +decimals = 6 + [APE] peggy_denom = peggy0x4d224452801ACEd8B2F0aebE155379bb5D594381 decimals = 18 @@ -845,6 +1038,10 @@ decimals = 6 peggy_denom = peggy0xBB0E17EF65F82Ab018d8EDd776e8DD940327B28b decimals = 18 +[Axelar Wrapped USDC] +peggy_denom = ibc/7E1AF94AD246BE522892751046F0C959B768642E5671CC3742264068D49553C0 +decimals = 6 + [BRETT] peggy_denom = factory/inj13jjdsa953w03dvecsr43dj5r6a2vzt7n0spncv/brett decimals = 6 @@ -861,6 +1058,10 @@ decimals = 8 peggy_denom = ibc/3A6DD3358D9F7ADD18CDE79BA10B400511A5DE4AE2C037D7C9639B52ADAF35C6 decimals = 6 +[DOJO] +peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj1zdj9kqnknztl2xclm5ssv25yre09f8908d4923 +decimals = 18 + [DOT] peggy_denom = ibc/624BA9DD171915A2B9EA70F69638B2CEA179959850C1A586F6C485498F29EDD4 decimals = 10 @@ -885,6 +1086,14 @@ decimals = 6 peggy_denom = peggy0xc944E90C64B2c07662A292be6244BDf05Cda44a7 decimals = 18 +[GYEN] +peggy_denom = peggy0xC08512927D12348F6620a698105e1BAac6EcD911 +decimals = 6 + +[HDRO] +peggy_denom = factory/inj1etz0laas6h7vemg3qtd67jpr6lh8v7xz7gfzqw/hdro +decimals = 6 + [HUAHUA] peggy_denom = ibc/E7807A46C0B7B44B350DA58F51F278881B863EC4DCA94635DAB39E52C30766CB decimals = 6 @@ -933,10 +1142,18 @@ decimals = 18 peggy_denom = factory/inj1xtel2knkt8hmc9dnzpjz6kdmacgcfmlv5f308w/ninja decimals = 6 +[Noble USD Coin] +peggy_denom = ibc/2CBC2EA121AE42563B08028466F37B600F2D7D4282342DE938283CC3FB2BC00E +decimals = 6 + [ORAI] peggy_denom = ibc/C20C0A822BD22B2CEF0D067400FCCFB6FAEEE9E91D360B4E0725BD522302D565 decimals = 6 +[PHUC] +peggy_denom = factory/inj1995xnrrtnmtdgjmx0g937vf28dwefhkhy6gy5e/phuc +decimals = 6 + [PUG] peggy_denom = peggy0xf9a06dE3F6639E6ee4F079095D5093644Ad85E8b decimals = 18 @@ -949,6 +1166,10 @@ decimals = 6 peggy_denom = peggy0x4a220E6096B25EADb88358cb44068A3248254675 decimals = 18 +[QUNT] +peggy_denom = factory/inj127l5a2wmkyvucxdlupqyac3y0v6wqfhq03ka64/qunt +decimals = 6 + [SNOWY] peggy_denom = factory/inj1ml33x7lkxk6x2x95d3alw4h84evlcdz2gnehmk/SNOWY decimals = 6 @@ -973,14 +1194,6 @@ decimals = 6 peggy_denom = peggy0x6B3595068778DD592e39A122f4f5a5cF09C90fE2 decimals = 18 -[SteadyBTC] -peggy_denom = peggy0x4986fD36b6b16f49b43282Ee2e24C5cF90ed166d -decimals = 18 - -[SteadyETH] -peggy_denom = peggy0x3F07A84eCdf494310D397d24c1C78B041D2fa622 -decimals = 18 - [TALIS] peggy_denom = factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis decimals = 6 @@ -997,12 +1210,12 @@ decimals = 18 peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj1q6zlut7gtkzknkk773jecujwsdkgq882akqksk decimals = 6 -[USDC] -peggy_denom = peggy0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 +[USD Coin (Wormhole from Solana)] +peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj12pwnhtv7yat2s30xuf4gdk9qm85v4j3e60dgvu decimals = 6 -[USDCso] -peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj12pwnhtv7yat2s30xuf4gdk9qm85v4j3e60dgvu +[USDC] +peggy_denom = peggy0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 decimals = 6 [USDT] @@ -1049,9 +1262,9 @@ decimals = 6 peggy_denom = peggy0xb2617246d0c6c0087f18703d576831899ca94f01 decimals = 18 -[axlUSDC] -peggy_denom = ibc/7E1AF94AD246BE522892751046F0C959B768642E5671CC3742264068D49553C0 -decimals = 6 +[hINJ] +peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj18luqttqyckgpddndh8hvaq25d5nfwjc78m56lc +decimals = 18 [nINJ] peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj13xlpypcwl5fuc84uhqzzqumnrcfpptyl6w3vrf @@ -1060,3 +1273,11 @@ decimals = 18 [stINJ] peggy_denom = ibc/AC87717EA002B0123B10A05063E69BCA274BA2C44D842AEEB41558D2856DCE93 decimals = 18 + +[steadyBTC] +peggy_denom = peggy0x4986fD36b6b16f49b43282Ee2e24C5cF90ed166d +decimals = 18 + +[steadyETH] +peggy_denom = peggy0x3F07A84eCdf494310D397d24c1C78B041D2fa622 +decimals = 18 diff --git a/pyinjective/denoms_testnet.ini b/pyinjective/denoms_testnet.ini index d81212d8..e8b5aa61 100644 --- a/pyinjective/denoms_testnet.ini +++ b/pyinjective/denoms_testnet.ini @@ -142,6 +142,24 @@ min_display_price_tick_size = 0.001 min_quantity_tick_size = 10000000000000 min_display_quantity_tick_size = 0.00001 +[0x21d4ee074f37f2a310929425e58f69850fca9f734d292bfc5ee48d3c28ea1c09] +description = 'Testnet Spot TEST2/INJ' +base = 6 +quote = 18 +min_price_tick_size = 100000000 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1000 +min_display_quantity_tick_size = 0.001 + +[0xf2ced33ef12a73962be92686503450cc4966feeb9cf6c809f4dc43acad5d7efb] +description = 'Testnet Spot TEST2/USDT' +base = 6 +quote = 6 +min_price_tick_size = 0.0001 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1000 +min_display_quantity_tick_size = 0.001 + [0xf02752c2c87728af7fd10a298a8a645261859eafd0295dcda7e2c5b45c8412cf] description = 'Testnet Spot stINJ/INJ' base = 18 @@ -205,6 +223,60 @@ min_display_price_tick_size = 0.001 min_quantity_tick_size = 100000 min_display_quantity_tick_size = 0.001 +[0xe93f09f7a06d507ff8b66f2969e1af931c9eb9ec3f640a6f87dbcd3456258466] +description = 'Testnet Spot Inj' +base = 18 +quote = 8 +min_price_tick_size = 0.0000000000001 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 1000000000000000 +min_display_quantity_tick_size = 0.001 + +[0xed865fd44f1bc9d46d978db415ed00444fac4f6aef7e09e2d0235f8d140b219f] +description = 'Testnet Spot MT/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000 +min_display_quantity_tick_size = 1000 + +[0x215970bfdea5c94d8e964a759d3ce6eae1d113900129cc8428267db5ccdb3d1a] +description = 'Testnet Spot INJ/USDC' +base = 18 +quote = 6 +min_price_tick_size = 0.000000000000001 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 10000000000000000 +min_display_quantity_tick_size = 0.01 + +[0xd8e9ea042ac67990134d8e024a251809b1b76c5f7df49f511858e040a285efca] +description = 'Testnet Spot HDRO/INJ' +base = 6 +quote = 18 +min_price_tick_size = 1000000 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 1000000 +min_display_quantity_tick_size = 1 + +[0x2d7f47811527bd721ce2e4e0ff27b0f3a281f65abcd41758baf157c8ddfcd910] +description = 'Testnet Spot hINJ/INJ' +base = 18 +quote = 18 +min_price_tick_size = 0.0001 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1000000000000000 +min_display_quantity_tick_size = 0.001 + +[0xe4b31c0112c89e0963b2db6884b416c17101a899e0ce6dc9f5dde79e6a01b52b] +description = 'Testnet Spot TEST1/INJ' +base = 6 +quote = 18 +min_price_tick_size = 1000000 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 1000000 +min_display_quantity_tick_size = 1 + [0x2e94326a421c3f66c15a3b663c7b1ab7fb6a5298b3a57759ecf07f0036793fc9] description = 'Testnet Derivative BTC/USDT PERP Pyth' base = 0 @@ -393,11 +465,19 @@ decimals = 18 peggy_denom = factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/atom decimals = 8 +[HDRO] +peggy_denom = factory/inj1pk7jhvjj2lufcghmvr7gl49dzwkk3xj0uqkwfk/hdro +decimals = 6 + [INJ] peggy_denom = inj decimals = 18 -[MITOTEST1] +[MT] +peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/mitotest2 +decimals = 6 + +[MitoTest1] peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/mitotest1 decimals = 18 @@ -409,6 +489,14 @@ decimals = 18 peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/projx decimals = 18 +[TEST1] +peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/test1 +decimals = 6 + +[TEST2] +peggy_denom = factory/inj1gvhyp8un5l9jpxpd90rdtj3ejd6qser2s2jxtz/test2 +decimals = 6 + [USD Coin] peggy_denom = factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/usdc decimals = 6 @@ -437,6 +525,10 @@ decimals = 18 peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/uzen decimals = 18 +[hINJ] +peggy_denom = factory/inj1hdvy6tl89llqy3ze8lv6mz5qh66sx9enn0jxg6/inj1mz7mfhgx8tuvjqut03qdujrkzwlx9xhcj6yldc +decimals = 18 + [stINJ] peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/stinj decimals = 18 diff --git a/pyproject.toml b/pyproject.toml index 81c1888f..85f36e5f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "injective-py" -version = "1.3.1" +version = "1.4.0" description = "Injective Python SDK, with Exchange API Client" authors = ["Injective Labs "] license = "Apache-2.0" @@ -51,6 +51,7 @@ pre-commit = "^3.4.0" flakeheaven = "^3.3.0" isort = "^5.12.0" black = "^23.9.1" +python-dotenv = "^1.0.1" [tool.flakeheaven] diff --git a/tests/client/chain/grpc/configurable_autz_query_servicer.py b/tests/client/chain/grpc/configurable_authz_query_servicer.py similarity index 100% rename from tests/client/chain/grpc/configurable_autz_query_servicer.py rename to tests/client/chain/grpc/configurable_authz_query_servicer.py diff --git a/tests/client/chain/grpc/configurable_distribution_query_servicer.py b/tests/client/chain/grpc/configurable_distribution_query_servicer.py new file mode 100644 index 00000000..d2e1d7da --- /dev/null +++ b/tests/client/chain/grpc/configurable_distribution_query_servicer.py @@ -0,0 +1,69 @@ +from collections import deque + +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + query_pb2 as distribution_query_pb, + query_pb2_grpc as distribution_query_grpc, +) + + +class ConfigurableDistributionQueryServicer(distribution_query_grpc.QueryServicer): + def __init__(self): + super().__init__() + self.distribution_params = deque() + self.validator_distribution_info_responses = deque() + self.validator_outstanding_rewards_responses = deque() + self.validator_commission_responses = deque() + self.validator_slashes_responses = deque() + self.delegation_rewards_responses = deque() + self.delegation_total_rewards_responses = deque() + self.delegator_validators_responses = deque() + self.delegator_withdraw_address_responses = deque() + self.community_pool_responses = deque() + + async def Params(self, request: distribution_query_pb.QueryParamsRequest, context=None, metadata=None): + return self.distribution_params.pop() + + async def ValidatorDistributionInfo( + self, request: distribution_query_pb.QueryValidatorDistributionInfoRequest, context=None, metadata=None + ): + return self.validator_distribution_info_responses.pop() + + async def ValidatorOutstandingRewards( + self, request: distribution_query_pb.QueryValidatorOutstandingRewardsRequest, context=None, metadata=None + ): + return self.validator_outstanding_rewards_responses.pop() + + async def ValidatorCommission( + self, request: distribution_query_pb.QueryValidatorCommissionRequest, context=None, metadata=None + ): + return self.validator_commission_responses.pop() + + async def ValidatorSlashes( + self, request: distribution_query_pb.QueryValidatorSlashesRequest, context=None, metadata=None + ): + return self.validator_slashes_responses.pop() + + async def DelegationRewards( + self, request: distribution_query_pb.QueryDelegationRewardsRequest, context=None, metadata=None + ): + return self.delegation_rewards_responses.pop() + + async def DelegationTotalRewards( + self, request: distribution_query_pb.QueryDelegationTotalRewardsRequest, context=None, metadata=None + ): + return self.delegation_total_rewards_responses.pop() + + async def DelegatorValidators( + self, request: distribution_query_pb.QueryDelegatorValidatorsRequest, context=None, metadata=None + ): + return self.delegator_validators_responses.pop() + + async def DelegatorWithdrawAddress( + self, request: distribution_query_pb.QueryDelegatorWithdrawAddressRequest, context=None, metadata=None + ): + return self.delegator_withdraw_address_responses.pop() + + async def CommunityPool( + self, request: distribution_query_pb.QueryCommunityPoolRequest, context=None, metadata=None + ): + return self.community_pool_responses.pop() diff --git a/tests/client/chain/grpc/configurable_exchange_query_servicer.py b/tests/client/chain/grpc/configurable_exchange_query_servicer.py new file mode 100644 index 00000000..23ded1de --- /dev/null +++ b/tests/client/chain/grpc/configurable_exchange_query_servicer.py @@ -0,0 +1,331 @@ +from collections import deque + +from pyinjective.proto.injective.exchange.v1beta1 import ( + query_pb2 as exchange_query_pb, + query_pb2_grpc as exchange_query_grpc, +) + + +class ConfigurableExchangeQueryServicer(exchange_query_grpc.QueryServicer): + def __init__(self): + super().__init__() + self.exchange_params = deque() + self.subaccount_deposits_responses = deque() + self.subaccount_deposit_responses = deque() + self.exchange_balances_responses = deque() + self.aggregate_volume_responses = deque() + self.aggregate_volumes_responses = deque() + self.aggregate_market_volume_responses = deque() + self.aggregate_market_volumes_responses = deque() + self.denom_decimal_responses = deque() + self.denom_decimals_responses = deque() + self.spot_markets_responses = deque() + self.spot_market_responses = deque() + self.full_spot_markets_responses = deque() + self.full_spot_market_responses = deque() + self.spot_orderbook_responses = deque() + self.trader_spot_orders_responses = deque() + self.account_address_spot_orders_responses = deque() + self.spot_orders_by_hashes_responses = deque() + self.subaccount_orders_responses = deque() + self.trader_spot_transient_orders_responses = deque() + self.spot_mid_price_and_tob_responses = deque() + self.derivative_mid_price_and_tob_responses = deque() + self.derivative_orderbook_responses = deque() + self.trader_derivative_orders_responses = deque() + self.account_address_derivative_orders_responses = deque() + self.derivative_orders_by_hashes_responses = deque() + self.trader_derivative_transient_orders_responses = deque() + self.derivative_markets_responses = deque() + self.derivative_market_responses = deque() + self.derivative_market_address_responses = deque() + self.subaccount_trade_nonce_responses = deque() + self.positions_responses = deque() + self.subaccount_positions_responses = deque() + self.subaccount_position_in_market_responses = deque() + self.subaccount_effective_position_in_market_responses = deque() + self.perpetual_market_info_responses = deque() + self.expiry_futures_market_info_responses = deque() + self.perpetual_market_funding_responses = deque() + self.subaccount_order_metadata_responses = deque() + self.trade_reward_points_responses = deque() + self.pending_trade_reward_points_responses = deque() + self.trade_reward_campaign_responses = deque() + self.fee_discount_account_info_responses = deque() + self.fee_discount_schedule_responses = deque() + self.balance_mismatches_responses = deque() + self.balance_with_balance_holds_responses = deque() + self.fee_discount_tier_statistics_responses = deque() + self.mito_vault_infos_responses = deque() + self.market_id_from_vault_responses = deque() + self.historical_trade_records_responses = deque() + self.is_opted_out_of_rewards_responses = deque() + self.opted_out_of_rewards_accounts_responses = deque() + self.market_volatility_responses = deque() + self.binary_options_markets_responses = deque() + self.trader_derivative_conditional_orders_responses = deque() + self.market_atomic_execution_fee_multiplier_responses = deque() + + async def QueryExchangeParams( + self, request: exchange_query_pb.QueryExchangeParamsRequest, context=None, metadata=None + ): + return self.exchange_params.pop() + + async def SubaccountDeposits( + self, request: exchange_query_pb.QuerySubaccountDepositsRequest, context=None, metadata=None + ): + return self.subaccount_deposits_responses.pop() + + async def SubaccountDeposit( + self, request: exchange_query_pb.QuerySubaccountDepositRequest, context=None, metadata=None + ): + return self.subaccount_deposit_responses.pop() + + async def ExchangeBalances( + self, request: exchange_query_pb.QueryExchangeBalancesRequest, context=None, metadata=None + ): + return self.exchange_balances_responses.pop() + + async def AggregateVolume( + self, request: exchange_query_pb.QueryAggregateVolumeRequest, context=None, metadata=None + ): + return self.aggregate_volume_responses.pop() + + async def AggregateVolumes( + self, request: exchange_query_pb.QueryAggregateVolumesRequest, context=None, metadata=None + ): + return self.aggregate_volumes_responses.pop() + + async def AggregateMarketVolume( + self, request: exchange_query_pb.QueryAggregateMarketVolumeRequest, context=None, metadata=None + ): + return self.aggregate_market_volume_responses.pop() + + async def AggregateMarketVolumes( + self, request: exchange_query_pb.QueryAggregateMarketVolumesRequest, context=None, metadata=None + ): + return self.aggregate_market_volumes_responses.pop() + + async def DenomDecimal(self, request: exchange_query_pb.QueryDenomDecimalRequest, context=None, metadata=None): + return self.denom_decimal_responses.pop() + + async def DenomDecimals(self, request: exchange_query_pb.QueryDenomDecimalsRequest, context=None, metadata=None): + return self.denom_decimals_responses.pop() + + async def SpotMarkets(self, request: exchange_query_pb.QuerySpotMarketsRequest, context=None, metadata=None): + return self.spot_markets_responses.pop() + + async def SpotMarket(self, request: exchange_query_pb.QuerySpotMarketRequest, context=None, metadata=None): + return self.spot_market_responses.pop() + + async def FullSpotMarkets( + self, request: exchange_query_pb.QueryFullSpotMarketsRequest, context=None, metadata=None + ): + return self.full_spot_markets_responses.pop() + + async def FullSpotMarket(self, request: exchange_query_pb.QueryFullSpotMarketRequest, context=None, metadata=None): + return self.full_spot_market_responses.pop() + + async def SpotOrderbook(self, request: exchange_query_pb.QuerySpotOrderbookRequest, context=None, metadata=None): + return self.spot_orderbook_responses.pop() + + async def TraderSpotOrders( + self, request: exchange_query_pb.QueryTraderSpotOrdersRequest, context=None, metadata=None + ): + return self.trader_spot_orders_responses.pop() + + async def AccountAddressSpotOrders( + self, request: exchange_query_pb.QueryAccountAddressSpotOrdersRequest, context=None, metadata=None + ): + return self.account_address_spot_orders_responses.pop() + + async def SpotOrdersByHashes( + self, request: exchange_query_pb.QuerySpotOrdersByHashesRequest, context=None, metadata=None + ): + return self.spot_orders_by_hashes_responses.pop() + + async def SubaccountOrders( + self, request: exchange_query_pb.QuerySubaccountOrdersRequest, context=None, metadata=None + ): + return self.subaccount_orders_responses.pop() + + async def TraderSpotTransientOrders( + self, request: exchange_query_pb.QueryTraderSpotOrdersRequest, context=None, metadata=None + ): + return self.trader_spot_transient_orders_responses.pop() + + async def SpotMidPriceAndTOB( + self, request: exchange_query_pb.QuerySpotMidPriceAndTOBRequest, context=None, metadata=None + ): + return self.spot_mid_price_and_tob_responses.pop() + + async def DerivativeMidPriceAndTOB( + self, request: exchange_query_pb.QueryDerivativeMidPriceAndTOBRequest, context=None, metadata=None + ): + return self.derivative_mid_price_and_tob_responses.pop() + + async def DerivativeOrderbook( + self, request: exchange_query_pb.QueryDerivativeOrderbookRequest, context=None, metadata=None + ): + return self.derivative_orderbook_responses.pop() + + async def TraderDerivativeOrders( + self, request: exchange_query_pb.QueryTraderDerivativeOrdersRequest, context=None, metadata=None + ): + return self.trader_derivative_orders_responses.pop() + + async def AccountAddressDerivativeOrders( + self, request: exchange_query_pb.QueryAccountAddressDerivativeOrdersRequest, context=None, metadata=None + ): + return self.account_address_derivative_orders_responses.pop() + + async def DerivativeOrdersByHashes( + self, request: exchange_query_pb.QueryDerivativeOrdersByHashesRequest, context=None, metadata=None + ): + return self.derivative_orders_by_hashes_responses.pop() + + async def TraderDerivativeTransientOrders( + self, request: exchange_query_pb.QueryTraderDerivativeOrdersRequest, context=None, metadata=None + ): + return self.trader_derivative_transient_orders_responses.pop() + + async def DerivativeMarkets( + self, request: exchange_query_pb.QueryDerivativeMarketsRequest, context=None, metadata=None + ): + return self.derivative_markets_responses.pop() + + async def DerivativeMarket( + self, request: exchange_query_pb.QueryDerivativeMarketRequest, context=None, metadata=None + ): + return self.derivative_market_responses.pop() + + async def DerivativeMarketAddress( + self, request: exchange_query_pb.QueryDerivativeMarketAddressRequest, context=None, metadata=None + ): + return self.derivative_market_address_responses.pop() + + async def SubaccountTradeNonce( + self, request: exchange_query_pb.QuerySubaccountTradeNonceRequest, context=None, metadata=None + ): + return self.subaccount_trade_nonce_responses.pop() + + async def Positions(self, request: exchange_query_pb.QueryPositionsRequest, context=None, metadata=None): + return self.positions_responses.pop() + + async def SubaccountPositions( + self, request: exchange_query_pb.QuerySubaccountPositionsRequest, context=None, metadata=None + ): + return self.subaccount_positions_responses.pop() + + async def SubaccountPositionInMarket( + self, request: exchange_query_pb.QuerySubaccountPositionInMarketRequest, context=None, metadata=None + ): + return self.subaccount_position_in_market_responses.pop() + + async def SubaccountEffectivePositionInMarket( + self, request: exchange_query_pb.QuerySubaccountEffectivePositionInMarketRequest, context=None, metadata=None + ): + return self.subaccount_effective_position_in_market_responses.pop() + + async def PerpetualMarketInfo( + self, request: exchange_query_pb.QueryPerpetualMarketInfoRequest, context=None, metadata=None + ): + return self.perpetual_market_info_responses.pop() + + async def ExpiryFuturesMarketInfo( + self, request: exchange_query_pb.QueryExpiryFuturesMarketInfoRequest, context=None, metadata=None + ): + return self.expiry_futures_market_info_responses.pop() + + async def PerpetualMarketFunding( + self, request: exchange_query_pb.QueryPerpetualMarketFundingRequest, context=None, metadata=None + ): + return self.perpetual_market_funding_responses.pop() + + async def SubaccountOrderMetadata( + self, request: exchange_query_pb.QuerySubaccountOrderMetadataRequest, context=None, metadata=None + ): + return self.subaccount_order_metadata_responses.pop() + + async def TradeRewardPoints( + self, request: exchange_query_pb.QueryTradeRewardPointsRequest, context=None, metadata=None + ): + return self.trade_reward_points_responses.pop() + + async def PendingTradeRewardPoints( + self, request: exchange_query_pb.QueryTradeRewardPointsRequest, context=None, metadata=None + ): + return self.pending_trade_reward_points_responses.pop() + + async def TradeRewardCampaign( + self, request: exchange_query_pb.QueryTradeRewardCampaignRequest, context=None, metadata=None + ): + return self.trade_reward_campaign_responses.pop() + + async def FeeDiscountAccountInfo( + self, request: exchange_query_pb.QueryFeeDiscountAccountInfoRequest, context=None, metadata=None + ): + return self.fee_discount_account_info_responses.pop() + + async def FeeDiscountSchedule( + self, request: exchange_query_pb.QueryFeeDiscountScheduleRequest, context=None, metadata=None + ): + return self.fee_discount_schedule_responses.pop() + + async def BalanceMismatches( + self, request: exchange_query_pb.QueryBalanceMismatchesRequest, context=None, metadata=None + ): + return self.balance_mismatches_responses.pop() + + async def BalanceWithBalanceHolds( + self, request: exchange_query_pb.QueryBalanceWithBalanceHoldsRequest, context=None, metadata=None + ): + return self.balance_with_balance_holds_responses.pop() + + async def FeeDiscountTierStatistics( + self, request: exchange_query_pb.QueryFeeDiscountTierStatisticsRequest, context=None, metadata=None + ): + return self.fee_discount_tier_statistics_responses.pop() + + async def MitoVaultInfos(self, request: exchange_query_pb.MitoVaultInfosRequest, context=None, metadata=None): + return self.mito_vault_infos_responses.pop() + + async def QueryMarketIDFromVault( + self, request: exchange_query_pb.QueryMarketIDFromVaultRequest, context=None, metadata=None + ): + return self.market_id_from_vault_responses.pop() + + async def HistoricalTradeRecords( + self, request: exchange_query_pb.QueryHistoricalTradeRecordsRequest, context=None, metadata=None + ): + return self.historical_trade_records_responses.pop() + + async def IsOptedOutOfRewards( + self, request: exchange_query_pb.QueryIsOptedOutOfRewardsRequest, context=None, metadata=None + ): + return self.is_opted_out_of_rewards_responses.pop() + + async def OptedOutOfRewardsAccounts( + self, request: exchange_query_pb.QueryOptedOutOfRewardsAccountsRequest, context=None, metadata=None + ): + return self.opted_out_of_rewards_accounts_responses.pop() + + async def MarketVolatility( + self, request: exchange_query_pb.QueryMarketVolatilityRequest, context=None, metadata=None + ): + return self.market_volatility_responses.pop() + + async def BinaryOptionsMarkets( + self, request: exchange_query_pb.QueryBinaryMarketsRequest, context=None, metadata=None + ): + return self.binary_options_markets_responses.pop() + + async def TraderDerivativeConditionalOrders( + self, request: exchange_query_pb.QueryTraderDerivativeConditionalOrdersRequest, context=None, metadata=None + ): + return self.trader_derivative_conditional_orders_responses.pop() + + async def MarketAtomicExecutionFeeMultiplier( + self, request: exchange_query_pb.QueryMarketAtomicExecutionFeeMultiplierRequest, context=None, metadata=None + ): + return self.market_atomic_execution_fee_multiplier_responses.pop() diff --git a/tests/client/chain/grpc/test_chain_grpc_authz_api.py b/tests/client/chain/grpc/test_chain_grpc_authz_api.py index e097ff66..9d1d5586 100644 --- a/tests/client/chain/grpc/test_chain_grpc_authz_api.py +++ b/tests/client/chain/grpc/test_chain_grpc_authz_api.py @@ -7,7 +7,7 @@ from pyinjective.core.network import Network from pyinjective.proto.cosmos.authz.v1beta1 import authz_pb2, query_pb2 as authz_query from pyinjective.proto.cosmos.base.query.v1beta1 import pagination_pb2 as pagination_pb -from tests.client.chain.grpc.configurable_autz_query_servicer import ConfigurableAuthZQueryServicer +from tests.client.chain.grpc.configurable_authz_query_servicer import ConfigurableAuthZQueryServicer @pytest.fixture diff --git a/tests/client/chain/grpc/test_chain_grpc_distribution_api.py b/tests/client/chain/grpc/test_chain_grpc_distribution_api.py new file mode 100644 index 00000000..9f8ee9a6 --- /dev/null +++ b/tests/client/chain/grpc/test_chain_grpc_distribution_api.py @@ -0,0 +1,338 @@ +import base64 + +import grpc +import pytest + +from pyinjective.client.chain.grpc.chain_grpc_distribution_api import ChainGrpcDistributionApi +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network +from pyinjective.proto.cosmos.base.query.v1beta1 import pagination_pb2 as pagination_pb +from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as coin_pb +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + distribution_pb2 as distribution_pb, + query_pb2 as distribution_query_pb, +) +from tests.client.chain.grpc.configurable_distribution_query_servicer import ConfigurableDistributionQueryServicer + + +@pytest.fixture +def distribution_servicer(): + return ConfigurableDistributionQueryServicer() + + +class TestChainGrpcAuthApi: + @pytest.mark.asyncio + async def test_fetch_module_params( + self, + distribution_servicer, + ): + params = distribution_pb.Params( + community_tax="0.050000000000000000", + base_proposer_reward="0.060000000000000000", + bonus_proposer_reward="0.070000000000000000", + withdraw_addr_enabled=True, + ) + + distribution_servicer.distribution_params.append(distribution_query_pb.QueryParamsResponse(params=params)) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + module_params = await api.fetch_module_params() + expected_params = { + "params": { + "communityTax": params.community_tax, + "baseProposerReward": params.base_proposer_reward, + "bonusProposerReward": params.bonus_proposer_reward, + "withdrawAddrEnabled": params.withdraw_addr_enabled, + } + } + + assert expected_params == module_params + + @pytest.mark.asyncio + async def test_fetch_validator_distribution_info( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + commission = coin_pb.DecCoin(denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", amount="54497408") + + distribution_servicer.validator_distribution_info_responses.append( + distribution_query_pb.QueryValidatorDistributionInfoResponse( + operator_address=operator, self_bond_rewards=[reward], commission=[commission] + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + validator_info = await api.fetch_validator_distribution_info(validator_address=operator) + expected_info = { + "operatorAddress": operator, + "selfBondRewards": [{"denom": reward.denom, "amount": reward.amount}], + "commission": [{"denom": commission.denom, "amount": commission.amount}], + } + + assert expected_info == validator_info + + @pytest.mark.asyncio + async def test_fetch_validator_outstanding_rewards( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + rewards = distribution_pb.ValidatorOutstandingRewards(rewards=[reward]) + + distribution_servicer.validator_outstanding_rewards_responses.append( + distribution_query_pb.QueryValidatorOutstandingRewardsResponse( + rewards=rewards, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + validator_rewards = await api.fetch_validator_outstanding_rewards(validator_address=operator) + expected_rewards = {"rewards": {"rewards": [{"denom": reward.denom, "amount": reward.amount}]}} + + assert expected_rewards == validator_rewards + + @pytest.mark.asyncio + async def test_fetch_validator_commission( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + first_commission = coin_pb.DecCoin(denom="inj", amount="1000000000") + commission = distribution_pb.ValidatorAccumulatedCommission(commission=[first_commission]) + + distribution_servicer.validator_commission_responses.append( + distribution_query_pb.QueryValidatorCommissionResponse( + commission=commission, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + commission = await api.fetch_validator_commission(validator_address=operator) + expected_commission = { + "commission": {"commission": [{"denom": first_commission.denom, "amount": first_commission.amount}]} + } + + assert expected_commission == commission + + @pytest.mark.asyncio + async def test_fetch_validator_slashes( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + slash = distribution_pb.ValidatorSlashEvent( + validator_period=1, + fraction="4", + ) + pagination = pagination_pb.PageResponse(total=2) + + distribution_servicer.validator_slashes_responses.append( + distribution_query_pb.QueryValidatorSlashesResponse( + slashes=[slash], + pagination=pagination, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + slashes = await api.fetch_validator_slashes( + validator_address=operator, + starting_height=20, + ending_height=100, + pagination=PaginationOption( + skip=0, + limit=100, + ), + ) + expected_slashes = { + "slashes": [ + { + "validatorPeriod": str(slash.validator_period), + "fraction": slash.fraction, + } + ], + "pagination": {"nextKey": base64.b64encode(pagination.next_key).decode(), "total": str(pagination.total)}, + } + + assert slashes == expected_slashes + + @pytest.mark.asyncio + async def test_fetch_delegation_rewards( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + validator = "injvaloper16gdnrnl224ylje5z9vd0vn0msym7p58f00qauj" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + + distribution_servicer.delegation_rewards_responses.append( + distribution_query_pb.QueryDelegationRewardsResponse( + rewards=[reward], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + rewards = await api.fetch_delegation_rewards( + delegator_address=delegator, + validator_address=validator, + ) + expected_rewards = {"rewards": [{"denom": reward.denom, "amount": reward.amount}]} + + assert rewards == expected_rewards + + @pytest.mark.asyncio + async def test_fetch_delegation_total_rewards( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + validator = "injvaloper16gdnrnl224ylje5z9vd0vn0msym7p58f00qauj" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + delegation_delegator_reward = distribution_pb.DelegationDelegatorReward( + validator_address=validator, + reward=[reward], + ) + total = coin_pb.DecCoin(denom="inj", amount="2000000000") + + distribution_servicer.delegation_total_rewards_responses.append( + distribution_query_pb.QueryDelegationTotalRewardsResponse( + rewards=[delegation_delegator_reward], + total=[total], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + rewards = await api.fetch_delegation_total_rewards( + delegator_address=delegator, + ) + expected_rewards = { + "rewards": [ + { + "validatorAddress": validator, + "reward": [{"denom": reward.denom, "amount": reward.amount}], + } + ], + "total": [{"denom": total.denom, "amount": total.amount}], + } + + assert rewards == expected_rewards + + @pytest.mark.asyncio + async def test_fetch_delegator_validators( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + validator = "injvaloper16gdnrnl224ylje5z9vd0vn0msym7p58f00qauj" + + distribution_servicer.delegator_validators_responses.append( + distribution_query_pb.QueryDelegatorValidatorsResponse( + validators=[validator], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + validators = await api.fetch_delegator_validators( + delegator_address=delegator, + ) + expected_validators = { + "validators": [validator], + } + + assert validators == expected_validators + + @pytest.mark.asyncio + async def test_fetch_delegator_withdraw_address( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + + distribution_servicer.delegator_withdraw_address_responses.append( + distribution_query_pb.QueryDelegatorWithdrawAddressResponse( + withdraw_address=delegator, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + withdraw_address = await api.fetch_delegator_withdraw_address( + delegator_address=delegator, + ) + expected_withdraw_address = { + "withdrawAddress": delegator, + } + + assert withdraw_address == expected_withdraw_address + + @pytest.mark.asyncio + async def test_fetch_community_pool( + self, + distribution_servicer, + ): + coin = coin_pb.DecCoin(denom="inj", amount="1000000000") + distribution_servicer.community_pool_responses.append( + distribution_query_pb.QueryCommunityPoolResponse( + pool=[coin], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + community_pool = await api.fetch_community_pool() + expected_community_pool = {"pool": [{"denom": coin.denom, "amount": coin.amount}]} + + assert community_pool == expected_community_pool + + async def _dummy_metadata_provider(self): + return None diff --git a/tests/client/chain/grpc/test_chain_grpc_exchange_api.py b/tests/client/chain/grpc/test_chain_grpc_exchange_api.py new file mode 100644 index 00000000..7ff77bbc --- /dev/null +++ b/tests/client/chain/grpc/test_chain_grpc_exchange_api.py @@ -0,0 +1,2579 @@ +import base64 + +import grpc +import pytest + +from pyinjective.client.chain.grpc.chain_grpc_exchange_api import ChainGrpcExchangeApi +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network +from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as coin_pb +from pyinjective.proto.injective.exchange.v1beta1 import ( + exchange_pb2 as exchange_pb, + genesis_pb2 as genesis_pb, + query_pb2 as exchange_query_pb, +) +from pyinjective.proto.injective.oracle.v1beta1 import oracle_pb2 as oracle_pb +from tests.client.chain.grpc.configurable_exchange_query_servicer import ConfigurableExchangeQueryServicer + + +@pytest.fixture +def exchange_servicer(): + return ConfigurableExchangeQueryServicer() + + +class TestChainGrpcBankApi: + @pytest.mark.asyncio + async def test_fetch_exchange_params( + self, + exchange_servicer, + ): + spot_market_instant_listing_fee = coin_pb.Coin(denom="inj", amount="10000000000000000000") + derivative_market_instant_listing_fee = coin_pb.Coin(denom="inj", amount="2000000000000000000000") + binary_options_market_instant_listing_fee = coin_pb.Coin(denom="inj", amount="30000000000000000000") + params = exchange_pb.Params( + spot_market_instant_listing_fee=spot_market_instant_listing_fee, + derivative_market_instant_listing_fee=derivative_market_instant_listing_fee, + default_spot_maker_fee_rate="-0.000100000000000000", + default_spot_taker_fee_rate="0.001000000000000000", + default_derivative_maker_fee_rate="-0.000100000000000000", + default_derivative_taker_fee_rate="0.001000000000000000", + default_initial_margin_ratio="0.050000000000000000", + default_maintenance_margin_ratio="0.020000000000000000", + default_funding_interval=3600, + funding_multiple=4600, + relayer_fee_share_rate="0.400000000000000000", + default_hourly_funding_rate_cap="0.000625000000000000", + default_hourly_interest_rate="0.000004166660000000", + max_derivative_order_side_count=20, + inj_reward_staked_requirement_threshold="25000000000000000000", + trading_rewards_vesting_duration=1209600, + liquidator_reward_share_rate="0.050000000000000000", + binary_options_market_instant_listing_fee=binary_options_market_instant_listing_fee, + atomic_market_order_access_level=2, + spot_atomic_market_order_fee_multiplier="2.000000000000000000", + derivative_atomic_market_order_fee_multiplier="2.000000000000000000", + binary_options_atomic_market_order_fee_multiplier="2.000000000000000000", + minimal_protocol_fee_rate="0.000010000000000000", + is_instant_derivative_market_launch_enabled=False, + post_only_mode_height_threshold=57078000, + ) + exchange_servicer.exchange_params.append(exchange_query_pb.QueryExchangeParamsResponse(params=params)) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + module_params = await api.fetch_exchange_params() + expected_params = { + "params": { + "spotMarketInstantListingFee": { + "amount": spot_market_instant_listing_fee.amount, + "denom": spot_market_instant_listing_fee.denom, + }, + "derivativeMarketInstantListingFee": { + "amount": derivative_market_instant_listing_fee.amount, + "denom": derivative_market_instant_listing_fee.denom, + }, + "defaultSpotMakerFeeRate": params.default_spot_maker_fee_rate, + "defaultSpotTakerFeeRate": params.default_spot_taker_fee_rate, + "defaultDerivativeMakerFeeRate": params.default_derivative_maker_fee_rate, + "defaultDerivativeTakerFeeRate": params.default_derivative_taker_fee_rate, + "defaultInitialMarginRatio": params.default_initial_margin_ratio, + "defaultMaintenanceMarginRatio": params.default_maintenance_margin_ratio, + "defaultFundingInterval": str(params.default_funding_interval), + "fundingMultiple": str(params.funding_multiple), + "relayerFeeShareRate": params.relayer_fee_share_rate, + "defaultHourlyFundingRateCap": params.default_hourly_funding_rate_cap, + "defaultHourlyInterestRate": params.default_hourly_interest_rate, + "maxDerivativeOrderSideCount": params.max_derivative_order_side_count, + "injRewardStakedRequirementThreshold": params.inj_reward_staked_requirement_threshold, + "tradingRewardsVestingDuration": str(params.trading_rewards_vesting_duration), + "liquidatorRewardShareRate": "0.050000000000000000", + "binaryOptionsMarketInstantListingFee": { + "amount": binary_options_market_instant_listing_fee.amount, + "denom": binary_options_market_instant_listing_fee.denom, + }, + "atomicMarketOrderAccessLevel": exchange_pb.AtomicMarketOrderAccessLevel.Name( + params.atomic_market_order_access_level + ), + "spotAtomicMarketOrderFeeMultiplier": params.spot_atomic_market_order_fee_multiplier, + "derivativeAtomicMarketOrderFeeMultiplier": params.derivative_atomic_market_order_fee_multiplier, + "binaryOptionsAtomicMarketOrderFeeMultiplier": params.binary_options_atomic_market_order_fee_multiplier, + "minimalProtocolFeeRate": params.minimal_protocol_fee_rate, + "isInstantDerivativeMarketLaunchEnabled": params.is_instant_derivative_market_launch_enabled, + "postOnlyModeHeightThreshold": str(params.post_only_mode_height_threshold), + } + } + + assert module_params == expected_params + + @pytest.mark.asyncio + async def test_fetch_subaccount_deposits( + self, + exchange_servicer, + ): + deposit_denom = "inj" + deposit = exchange_pb.Deposit( + available_balance="1000000000000000000", + total_balance="2000000000000000000", + ) + exchange_servicer.subaccount_deposits_responses.append( + exchange_query_pb.QuerySubaccountDepositsResponse(deposits={deposit_denom: deposit}) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + deposits = await api.fetch_subaccount_deposits( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + subaccount_trader="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7", + subaccount_nonce=1, + ) + expected_deposits = { + "deposits": { + deposit_denom: { + "availableBalance": deposit.available_balance, + "totalBalance": deposit.total_balance, + }, + } + } + + assert deposits == expected_deposits + + @pytest.mark.asyncio + async def test_fetch_subaccount_deposit( + self, + exchange_servicer, + ): + deposit = exchange_pb.Deposit( + available_balance="1000000000000000000", + total_balance="2000000000000000000", + ) + exchange_servicer.subaccount_deposit_responses.append( + exchange_query_pb.QuerySubaccountDepositResponse(deposits=deposit) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + deposit_response = await api.fetch_subaccount_deposit( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="inj", + ) + expected_deposit = { + "deposits": { + "availableBalance": deposit.available_balance, + "totalBalance": deposit.total_balance, + } + } + + assert deposit_response == expected_deposit + + @pytest.mark.asyncio + async def test_fetch_exchange_balances( + self, + exchange_servicer, + ): + deposit = exchange_pb.Deposit( + available_balance="1000000000000000000", + total_balance="2000000000000000000", + ) + balance = genesis_pb.Balance( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="inj", + deposits=deposit, + ) + exchange_servicer.exchange_balances_responses.append( + exchange_query_pb.QueryExchangeBalancesResponse(balances=[balance]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + balances_response = await api.fetch_exchange_balances() + expected_balances = { + "balances": [ + { + "subaccountId": balance.subaccount_id, + "denom": balance.denom, + "deposits": { + "availableBalance": deposit.available_balance, + "totalBalance": deposit.total_balance, + }, + }, + ] + } + + assert balances_response == expected_balances + + @pytest.mark.asyncio + async def test_fetch_aggregate_volume( + self, + exchange_servicer, + ): + volume = exchange_pb.VolumeRecord( + maker_volume="1000000000000000000", + taker_volume="2000000000000000000", + ) + market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=volume, + ) + exchange_servicer.aggregate_volume_responses.append( + exchange_query_pb.QueryAggregateVolumeResponse( + aggregate_volumes=[market_volume], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_volume(account="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r") + expected_volume = { + "aggregateVolumes": [ + { + "marketId": market_volume.market_id, + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + }, + }, + ] + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_aggregate_volumes( + self, + exchange_servicer, + ): + acc_volume = exchange_pb.VolumeRecord( + maker_volume="1000000000000000000", + taker_volume="2000000000000000000", + ) + account_market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=acc_volume, + ) + account_volume = exchange_pb.AggregateAccountVolumeRecord( + account="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + market_volumes=[account_market_volume], + ) + volume = exchange_pb.VolumeRecord( + maker_volume="3000000000000000000", + taker_volume="4000000000000000000", + ) + market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=volume, + ) + exchange_servicer.aggregate_volumes_responses.append( + exchange_query_pb.QueryAggregateVolumesResponse( + aggregate_account_volumes=[account_volume], + aggregate_market_volumes=[market_volume], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_volumes( + accounts=[account_volume.account], + market_ids=[account_market_volume.market_id], + ) + expected_volume = { + "aggregateAccountVolumes": [ + { + "account": account_volume.account, + "marketVolumes": [ + { + "marketId": account_market_volume.market_id, + "volume": { + "makerVolume": acc_volume.maker_volume, + "takerVolume": acc_volume.taker_volume, + }, + }, + ], + }, + ], + "aggregateMarketVolumes": [ + { + "marketId": market_volume.market_id, + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + }, + }, + ], + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_aggregate_market_volume( + self, + exchange_servicer, + ): + volume = exchange_pb.VolumeRecord( + maker_volume="1000000000000000000", + taker_volume="2000000000000000000", + ) + exchange_servicer.aggregate_market_volume_responses.append( + exchange_query_pb.QueryAggregateMarketVolumeResponse( + volume=volume, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_market_volume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + ) + expected_volume = { + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + } + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_aggregate_market_volumes( + self, + exchange_servicer, + ): + volume = exchange_pb.VolumeRecord( + maker_volume="3000000000000000000", + taker_volume="4000000000000000000", + ) + market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=volume, + ) + exchange_servicer.aggregate_market_volumes_responses.append( + exchange_query_pb.QueryAggregateMarketVolumesResponse( + volumes=[market_volume], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_market_volumes( + market_ids=[market_volume.market_id], + ) + expected_volume = { + "volumes": [ + { + "marketId": market_volume.market_id, + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + }, + }, + ], + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_denom_decimal( + self, + exchange_servicer, + ): + decimal = 18 + exchange_servicer.denom_decimal_responses.append( + exchange_query_pb.QueryDenomDecimalResponse( + decimal=decimal, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + denom_decimal = await api.fetch_denom_decimal(denom="inj") + expected_decimal = {"decimal": str(decimal)} + + assert denom_decimal == expected_decimal + + @pytest.mark.asyncio + async def test_fetch_denom_decimals( + self, + exchange_servicer, + ): + denom_decimal = exchange_pb.DenomDecimals( + denom="inj", + decimals=18, + ) + exchange_servicer.denom_decimals_responses.append( + exchange_query_pb.QueryDenomDecimalsResponse( + denom_decimals=[denom_decimal], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + denom_decimals = await api.fetch_denom_decimals(denoms=[denom_decimal.denom]) + expected_decimals = { + "denomDecimals": [ + { + "denom": denom_decimal.denom, + "decimals": str(denom_decimal.decimals), + } + ] + } + + assert denom_decimals == expected_decimals + + @pytest.mark.asyncio + async def test_fetch_spot_markets( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + exchange_servicer.spot_markets_responses.append( + exchange_query_pb.QuerySpotMarketsResponse( + markets=[market], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + markets = await api.fetch_spot_markets( + status=status_string, + market_ids=[market.market_id], + ) + expected_markets = { + "markets": [ + { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + } + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_spot_market( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + exchange_servicer.spot_market_responses.append( + exchange_query_pb.QuerySpotMarketResponse( + market=market, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + response_market = await api.fetch_spot_market( + market_id=market.market_id, + ) + expected_market = { + "market": { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": exchange_pb.MarketStatus.Name(market.status), + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + } + } + + assert response_market == expected_market + + @pytest.mark.asyncio + async def test_fetch_full_spot_markets( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullSpotMarket( + market=market, + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.full_spot_markets_responses.append( + exchange_query_pb.QueryFullSpotMarketsResponse( + markets=[full_market], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + markets = await api.fetch_full_spot_markets( + status=status_string, + market_ids=[market.market_id], + with_mid_price_and_tob=True, + ) + expected_markets = { + "markets": [ + { + "market": { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_full_spot_market( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullSpotMarket( + market=market, + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.full_spot_market_responses.append( + exchange_query_pb.QueryFullSpotMarketResponse( + market=full_market, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + market_response = await api.fetch_full_spot_market( + market_id=market.market_id, + with_mid_price_and_tob=True, + ) + expected_market = { + "market": { + "market": { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + } + + assert market_response == expected_market + + @pytest.mark.asyncio + async def test_fetch_spot_orderbook( + self, + exchange_servicer, + ): + buy_price_level = exchange_pb.Level( + p="1000000000000000000", + q="1000000000000000", + ) + sell_price_level = exchange_pb.Level( + p="2000000000000000000", + q="2000000000000000", + ) + exchange_servicer.spot_orderbook_responses.append( + exchange_query_pb.QuerySpotOrderbookResponse( + buys_price_level=[buy_price_level], + sells_price_level=[sell_price_level], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orderbook = await api.fetch_spot_orderbook( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + order_side="Side_Unspecified", + limit_cumulative_notional="1000000000000000000", + limit_cumulative_quantity="1000000000000000", + pagination=PaginationOption(limit=100), + ) + expected_orderbook = { + "buysPriceLevel": [ + { + "p": buy_price_level.p, + "q": buy_price_level.q, + } + ], + "sellsPriceLevel": [ + { + "p": sell_price_level.p, + "q": sell_price_level.q, + } + ], + } + + assert orderbook == expected_orderbook + + @pytest.mark.asyncio + async def test_fetch_trader_spot_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_spot_orders_responses.append( + exchange_query_pb.QueryTraderSpotOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_account_address_spot_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.account_address_spot_orders_responses.append( + exchange_query_pb.QueryAccountAddressSpotOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_account_address_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + account_address="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_spot_orders_by_hashes( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.spot_orders_by_hashes_responses.append( + exchange_query_pb.QuerySpotOrdersByHashesResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_spot_orders_by_hashes( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + order_hashes=[order.order_hash], + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_subaccount_orders( + self, + exchange_servicer, + ): + buy_subaccount_order = exchange_pb.SubaccountOrder( + price="1000000000000000000", + quantity="1000000000000000", + isReduceOnly=False, + ) + buy_order = exchange_pb.SubaccountOrderData( + order=buy_subaccount_order, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849".encode(), + ) + sell_subaccount_order = exchange_pb.SubaccountOrder( + price="2000000000000000000", + quantity="2000000000000000", + isReduceOnly=False, + ) + sell_order = exchange_pb.SubaccountOrderData( + order=sell_subaccount_order, + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2".encode(), + ) + exchange_servicer.subaccount_orders_responses.append( + exchange_query_pb.QuerySubaccountOrdersResponse( + buy_orders=[buy_order], + sell_orders=[sell_order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_subaccount_orders( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + expected_orders = { + "buyOrders": [ + { + "order": { + "price": buy_subaccount_order.price, + "quantity": buy_subaccount_order.quantity, + "isReduceOnly": buy_subaccount_order.isReduceOnly, + }, + "orderHash": base64.b64encode(buy_order.order_hash).decode(), + } + ], + "sellOrders": [ + { + "order": { + "price": sell_subaccount_order.price, + "quantity": sell_subaccount_order.quantity, + "isReduceOnly": sell_subaccount_order.isReduceOnly, + }, + "orderHash": base64.b64encode(sell_order.order_hash).decode(), + } + ], + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_trader_spot_transient_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_spot_transient_orders_responses.append( + exchange_query_pb.QueryTraderSpotOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_spot_transient_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_spot_mid_price_and_tob( + self, + exchange_servicer, + ): + response = exchange_query_pb.QuerySpotMidPriceAndTOBResponse( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + exchange_servicer.spot_mid_price_and_tob_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + prices = await api.fetch_spot_mid_price_and_tob( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + expected_prices = { + "midPrice": response.mid_price, + "bestBuyPrice": response.best_buy_price, + "bestSellPrice": response.best_sell_price, + } + + assert prices == expected_prices + + @pytest.mark.asyncio + async def test_fetch_derivative_mid_price_and_tob( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryDerivativeMidPriceAndTOBResponse( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + exchange_servicer.derivative_mid_price_and_tob_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + prices = await api.fetch_derivative_mid_price_and_tob( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + expected_prices = { + "midPrice": response.mid_price, + "bestBuyPrice": response.best_buy_price, + "bestSellPrice": response.best_sell_price, + } + + assert prices == expected_prices + + @pytest.mark.asyncio + async def test_fetch_derivative_orderbook( + self, + exchange_servicer, + ): + buy_price_level = exchange_pb.Level( + p="1000000000000000000", + q="1000000000000000", + ) + sell_price_level = exchange_pb.Level( + p="2000000000000000000", + q="2000000000000000", + ) + exchange_servicer.derivative_orderbook_responses.append( + exchange_query_pb.QueryDerivativeOrderbookResponse( + buys_price_level=[buy_price_level], + sells_price_level=[sell_price_level], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orderbook = await api.fetch_derivative_orderbook( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + limit_cumulative_notional="1000000000000000000", + pagination=PaginationOption(limit=100), + ) + expected_orderbook = { + "buysPriceLevel": [ + { + "p": buy_price_level.p, + "q": buy_price_level.q, + } + ], + "sellsPriceLevel": [ + { + "p": sell_price_level.p, + "q": sell_price_level.q, + } + ], + } + + assert orderbook == expected_orderbook + + @pytest.mark.asyncio + async def test_fetch_trader_derivative_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_derivative_orders_responses.append( + exchange_query_pb.QueryTraderDerivativeOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_derivative_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_account_address_derivative_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.account_address_derivative_orders_responses.append( + exchange_query_pb.QueryAccountAddressDerivativeOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_account_address_derivative_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + account_address="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_derivative_orders_by_hashes( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.derivative_orders_by_hashes_responses.append( + exchange_query_pb.QueryDerivativeOrdersByHashesResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_derivative_orders_by_hashes( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + order_hashes=[order.order_hash], + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_trader_derivative_transient_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_derivative_transient_orders_responses.append( + exchange_query_pb.QueryTraderDerivativeOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_derivative_transient_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_derivative_markets( + self, + exchange_servicer, + ): + market = exchange_pb.DerivativeMarket( + ticker="20250608/USDT", + oracle_base="0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3", + oracle_quote="0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588", + oracle_type=9, + oracle_scale_factor=6, + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + initial_margin_ratio="50000000000000000", + maintenance_margin_ratio="20000000000000000", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="400000000000000000", + isPerpetual=True, + status=1, + min_price_tick_size="100000000000000000000", + min_quantity_tick_size="1000000000000000", + ) + market_info = exchange_pb.PerpetualMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + hourly_funding_rate_cap="625000000000000", + hourly_interest_rate="4166660000000", + next_funding_timestamp=1708099200, + funding_interval=3600, + ) + funding_info = exchange_pb.PerpetualMarketFunding( + cumulative_funding="-107853477278881692857461", + cumulative_price="0", + last_timestamp=1708099200, + ) + perpetual_info = exchange_query_pb.PerpetualMarketState( + market_info=market_info, + funding_info=funding_info, + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullDerivativeMarket( + market=market, + perpetual_info=perpetual_info, + mark_price="33803835513327368963000000", + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.derivative_markets_responses.append( + exchange_query_pb.QueryDerivativeMarketsResponse( + markets=[full_market], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + markets = await api.fetch_derivative_markets( + status=status_string, + market_ids=[market.market_id], + ) + expected_markets = { + "markets": [ + { + "market": { + "ticker": market.ticker, + "oracleBase": market.oracle_base, + "oracleQuote": market.oracle_quote, + "oracleType": oracle_pb.OracleType.Name(market.oracle_type), + "oracleScaleFactor": market.oracle_scale_factor, + "quoteDenom": market.quote_denom, + "marketId": market.market_id, + "initialMarginRatio": market.initial_margin_ratio, + "maintenanceMarginRatio": market.maintenance_margin_ratio, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "isPerpetual": market.isPerpetual, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "perpetualInfo": { + "marketInfo": { + "marketId": market_info.market_id, + "hourlyFundingRateCap": market_info.hourly_funding_rate_cap, + "hourlyInterestRate": market_info.hourly_interest_rate, + "nextFundingTimestamp": str(market_info.next_funding_timestamp), + "fundingInterval": str(market_info.funding_interval), + }, + "fundingInfo": { + "cumulativeFunding": funding_info.cumulative_funding, + "cumulativePrice": funding_info.cumulative_price, + "lastTimestamp": str(funding_info.last_timestamp), + }, + }, + "markPrice": full_market.mark_price, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_derivative_market( + self, + exchange_servicer, + ): + market = exchange_pb.DerivativeMarket( + ticker="INJ/USDT PERP", + oracle_base="0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3", + oracle_quote="0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588", + oracle_type=9, + oracle_scale_factor=6, + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + initial_margin_ratio="50000000000000000", + maintenance_margin_ratio="20000000000000000", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="400000000000000000", + isPerpetual=True, + status=1, + min_price_tick_size="100000000000000000000", + min_quantity_tick_size="1000000000000000", + ) + market_info = exchange_pb.PerpetualMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + hourly_funding_rate_cap="625000000000000", + hourly_interest_rate="4166660000000", + next_funding_timestamp=1708099200, + funding_interval=3600, + ) + funding_info = exchange_pb.PerpetualMarketFunding( + cumulative_funding="-107853477278881692857461", + cumulative_price="0", + last_timestamp=1708099200, + ) + perpetual_info = exchange_query_pb.PerpetualMarketState( + market_info=market_info, + funding_info=funding_info, + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullDerivativeMarket( + market=market, + perpetual_info=perpetual_info, + mark_price="33803835513327368963000000", + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.derivative_market_responses.append( + exchange_query_pb.QueryDerivativeMarketResponse( + market=full_market, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + market_response = await api.fetch_derivative_market( + market_id=market.market_id, + ) + expected_market = { + "market": { + "market": { + "ticker": market.ticker, + "oracleBase": market.oracle_base, + "oracleQuote": market.oracle_quote, + "oracleType": oracle_pb.OracleType.Name(market.oracle_type), + "oracleScaleFactor": market.oracle_scale_factor, + "quoteDenom": market.quote_denom, + "marketId": market.market_id, + "initialMarginRatio": market.initial_margin_ratio, + "maintenanceMarginRatio": market.maintenance_margin_ratio, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "isPerpetual": market.isPerpetual, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "perpetualInfo": { + "marketInfo": { + "marketId": market_info.market_id, + "hourlyFundingRateCap": market_info.hourly_funding_rate_cap, + "hourlyInterestRate": market_info.hourly_interest_rate, + "nextFundingTimestamp": str(market_info.next_funding_timestamp), + "fundingInterval": str(market_info.funding_interval), + }, + "fundingInfo": { + "cumulativeFunding": funding_info.cumulative_funding, + "cumulativePrice": funding_info.cumulative_price, + "lastTimestamp": str(funding_info.last_timestamp), + }, + }, + "markPrice": full_market.mark_price, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + } + + assert market_response == expected_market + + @pytest.mark.asyncio + async def test_fetch_derivative_market_address( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryDerivativeMarketAddressResponse( + address="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9", + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + ) + exchange_servicer.derivative_market_address_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + address = await api.fetch_derivative_market_address( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + expected_address = { + "address": response.address, + "subaccountId": response.subaccount_id, + } + + assert address == expected_address + + @pytest.mark.asyncio + async def test_fetch_subaccount_trade_nonce( + self, + exchange_servicer, + ): + response = exchange_query_pb.QuerySubaccountTradeNonceResponse(nonce=1234567879) + exchange_servicer.subaccount_trade_nonce_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + nonce = await api.fetch_subaccount_trade_nonce( + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + ) + expected_nonce = { + "nonce": response.nonce, + } + + assert nonce == expected_nonce + + @pytest.mark.asyncio + async def test_fetch_positions( + self, + exchange_servicer, + ): + position = exchange_pb.Position( + isLong=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + margin="2000000000000000000000000000000000", + cumulative_funding_entry="4000000", + ) + derivative_position = genesis_pb.DerivativePosition( + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + position=position, + ) + exchange_servicer.positions_responses.append( + exchange_query_pb.QueryPositionsResponse(state=[derivative_position]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + positions = await api.fetch_positions() + expected_positions = { + "state": [ + { + "subaccountId": derivative_position.subaccount_id, + "marketId": derivative_position.market_id, + "position": { + "isLong": position.isLong, + "quantity": position.quantity, + "entryPrice": position.entry_price, + "margin": position.margin, + "cumulativeFundingEntry": position.cumulative_funding_entry, + }, + }, + ], + } + + assert positions == expected_positions + + @pytest.mark.asyncio + async def test_fetch_subaccount_positions( + self, + exchange_servicer, + ): + position = exchange_pb.Position( + isLong=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + margin="2000000000000000000000000000000000", + cumulative_funding_entry="4000000", + ) + derivative_position = genesis_pb.DerivativePosition( + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + position=position, + ) + exchange_servicer.subaccount_positions_responses.append( + exchange_query_pb.QuerySubaccountPositionsResponse(state=[derivative_position]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + positions = await api.fetch_subaccount_positions(subaccount_id=derivative_position.subaccount_id) + expected_positions = { + "state": [ + { + "subaccountId": derivative_position.subaccount_id, + "marketId": derivative_position.market_id, + "position": { + "isLong": position.isLong, + "quantity": position.quantity, + "entryPrice": position.entry_price, + "margin": position.margin, + "cumulativeFundingEntry": position.cumulative_funding_entry, + }, + }, + ], + } + + assert positions == expected_positions + + @pytest.mark.asyncio + async def test_fetch_subaccount_position_in_market( + self, + exchange_servicer, + ): + subaccount_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000" + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + position = exchange_pb.Position( + isLong=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + margin="2000000000000000000000000000000000", + cumulative_funding_entry="4000000", + ) + exchange_servicer.subaccount_position_in_market_responses.append( + exchange_query_pb.QuerySubaccountPositionInMarketResponse(state=position) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + position_response = await api.fetch_subaccount_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + expected_position = { + "state": { + "isLong": position.isLong, + "quantity": position.quantity, + "entryPrice": position.entry_price, + "margin": position.margin, + "cumulativeFundingEntry": position.cumulative_funding_entry, + }, + } + + assert position_response == expected_position + + @pytest.mark.asyncio + async def test_fetch_subaccount_effective_position_in_market( + self, + exchange_servicer, + ): + subaccount_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000" + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + + effective_position = exchange_query_pb.EffectivePosition( + is_long=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + effective_margin="2000000000000000000000000000000000", + ) + exchange_servicer.subaccount_effective_position_in_market_responses.append( + exchange_query_pb.QuerySubaccountEffectivePositionInMarketResponse(state=effective_position) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + position_response = await api.fetch_subaccount_effective_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + expected_position = { + "state": { + "isLong": effective_position.is_long, + "quantity": effective_position.quantity, + "entryPrice": effective_position.entry_price, + "effectiveMargin": effective_position.effective_margin, + }, + } + + assert position_response == expected_position + + @pytest.mark.asyncio + async def test_fetch_perpetual_market_info( + self, + exchange_servicer, + ): + perpetual_market_info = exchange_pb.PerpetualMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + hourly_funding_rate_cap="625000000000000", + hourly_interest_rate="4166660000000", + next_funding_timestamp=1708099200, + funding_interval=3600, + ) + exchange_servicer.perpetual_market_info_responses.append( + exchange_query_pb.QueryPerpetualMarketInfoResponse(info=perpetual_market_info) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + market_info = await api.fetch_perpetual_market_info(market_id=perpetual_market_info.market_id) + expected_market_info = { + "info": { + "marketId": perpetual_market_info.market_id, + "hourlyFundingRateCap": perpetual_market_info.hourly_funding_rate_cap, + "hourlyInterestRate": perpetual_market_info.hourly_interest_rate, + "nextFundingTimestamp": str(perpetual_market_info.next_funding_timestamp), + "fundingInterval": str(perpetual_market_info.funding_interval), + } + } + + assert market_info == expected_market_info + + @pytest.mark.asyncio + async def test_fetch_expiry_futures_market_info( + self, + exchange_servicer, + ): + expiry_futures_market_info = exchange_pb.ExpiryFuturesMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + expiration_timestamp=1708099200, + twap_start_timestamp=1705566200, + expiration_twap_start_price_cumulative="1000000000000000000", + settlement_price="2000000000000000000", + ) + exchange_servicer.expiry_futures_market_info_responses.append( + exchange_query_pb.QueryExpiryFuturesMarketInfoResponse(info=expiry_futures_market_info) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + market_info = await api.fetch_expiry_futures_market_info(market_id=expiry_futures_market_info.market_id) + expected_market_info = { + "info": { + "marketId": expiry_futures_market_info.market_id, + "expirationTimestamp": str(expiry_futures_market_info.expiration_timestamp), + "twapStartTimestamp": str(expiry_futures_market_info.twap_start_timestamp), + "expirationTwapStartPriceCumulative": expiry_futures_market_info.expiration_twap_start_price_cumulative, + "settlementPrice": expiry_futures_market_info.settlement_price, + } + } + + assert market_info == expected_market_info + + @pytest.mark.asyncio + async def test_fetch_perpetual_market_funding( + self, + exchange_servicer, + ): + perpetual_market_funding = exchange_pb.PerpetualMarketFunding( + cumulative_funding="-107853477278881692857461", + cumulative_price="0", + last_timestamp=1708099200, + ) + exchange_servicer.perpetual_market_funding_responses.append( + exchange_query_pb.QueryPerpetualMarketFundingResponse(state=perpetual_market_funding) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + funding = await api.fetch_perpetual_market_funding( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + ) + expected_funding = { + "state": { + "cumulativeFunding": perpetual_market_funding.cumulative_funding, + "cumulativePrice": perpetual_market_funding.cumulative_price, + "lastTimestamp": str(perpetual_market_funding.last_timestamp), + } + } + + assert funding == expected_funding + + @pytest.mark.asyncio + async def test_fetch_subaccount_order_metadata( + self, + exchange_servicer, + ): + metadata = exchange_pb.SubaccountOrderbookMetadata( + vanilla_limit_order_count=1, + reduce_only_limit_order_count=2, + aggregate_reduce_only_quantity="1000000000000000", + aggregate_vanilla_quantity="2000000000000000", + vanilla_conditional_order_count=3, + reduce_only_conditional_order_count=4, + ) + subaccount_order_metadata = exchange_query_pb.SubaccountOrderbookMetadataWithMarket( + metadata=metadata, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + isBuy=True, + ) + exchange_servicer.subaccount_order_metadata_responses.append( + exchange_query_pb.QuerySubaccountOrderMetadataResponse(metadata=[subaccount_order_metadata]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + metadata_response = await api.fetch_subaccount_order_metadata( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001" + ) + expected_metadata = { + "metadata": [ + { + "metadata": { + "vanillaLimitOrderCount": metadata.vanilla_limit_order_count, + "reduceOnlyLimitOrderCount": metadata.reduce_only_limit_order_count, + "aggregateReduceOnlyQuantity": metadata.aggregate_reduce_only_quantity, + "aggregateVanillaQuantity": metadata.aggregate_vanilla_quantity, + "vanillaConditionalOrderCount": metadata.vanilla_conditional_order_count, + "reduceOnlyConditionalOrderCount": metadata.reduce_only_conditional_order_count, + }, + "marketId": subaccount_order_metadata.market_id, + "isBuy": subaccount_order_metadata.isBuy, + }, + ] + } + + assert metadata_response == expected_metadata + + @pytest.mark.asyncio + async def test_fetch_trade_reward_points( + self, + exchange_servicer, + ): + points = "40" + response = exchange_query_pb.QueryTradeRewardPointsResponse(account_trade_reward_points=[points]) + exchange_servicer.trade_reward_points_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + trade_reward_points = await api.fetch_trade_reward_points( + accounts=["inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"], + pending_pool_timestamp=1708099200, + ) + expected_trade_reward_points = {"accountTradeRewardPoints": [points]} + + assert trade_reward_points == expected_trade_reward_points + + @pytest.mark.asyncio + async def test_fetch_pending_trade_reward_points( + self, + exchange_servicer, + ): + points = "40" + response = exchange_query_pb.QueryTradeRewardPointsResponse(account_trade_reward_points=[points]) + exchange_servicer.pending_trade_reward_points_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + trade_reward_points = await api.fetch_pending_trade_reward_points( + accounts=["inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"], + pending_pool_timestamp=1708099200, + ) + expected_trade_reward_points = {"accountTradeRewardPoints": [points]} + + assert trade_reward_points == expected_trade_reward_points + + @pytest.mark.asyncio + async def test_fetch_trade_reward_campaign( + self, + exchange_servicer, + ): + spot_market_multiplier = exchange_pb.PointsMultiplier( + maker_points_multiplier="10.0", + taker_points_multiplier="5.0", + ) + derivative_market_multiplier = exchange_pb.PointsMultiplier( + maker_points_multiplier="9.0", + taker_points_multiplier="6.0", + ) + trading_reward_boost_info = exchange_pb.TradingRewardCampaignBoostInfo( + boosted_spot_market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00aaf7"], + spot_market_multipliers=[spot_market_multiplier], + boosted_derivative_market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"], + derivative_market_multipliers=[derivative_market_multiplier], + ) + trading_reward_campaign_info = exchange_pb.TradingRewardCampaignInfo( + campaign_duration_seconds=3600, + quote_denoms=["peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"], + trading_reward_boost_info=trading_reward_boost_info, + disqualified_market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00aaf7"], + ) + reward = coin_pb.Coin( + amount="1000000000000000000", + denom="inj", + ) + trading_reward_pool_campaign_schedule = exchange_pb.CampaignRewardPool( + start_timestamp=1708099200, + max_campaign_rewards=[reward], + ) + total_trade_reward_points = "40" + pending_reward = coin_pb.Coin( + amount="2000000000000000000", + denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + ) + pending_trading_reward_pool_campaign_schedule = exchange_pb.CampaignRewardPool( + start_timestamp=1709099200, + max_campaign_rewards=[pending_reward], + ) + pending_total_trade_reward_points = "80" + response = exchange_query_pb.QueryTradeRewardCampaignResponse( + trading_reward_campaign_info=trading_reward_campaign_info, + trading_reward_pool_campaign_schedule=[trading_reward_pool_campaign_schedule], + total_trade_reward_points=total_trade_reward_points, + pending_trading_reward_pool_campaign_schedule=[pending_trading_reward_pool_campaign_schedule], + pending_total_trade_reward_points=[pending_total_trade_reward_points], + ) + exchange_servicer.trade_reward_campaign_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + trade_reward_campaign = await api.fetch_trade_reward_campaign() + expected_campaign = { + "tradingRewardCampaignInfo": { + "campaignDurationSeconds": str(trading_reward_campaign_info.campaign_duration_seconds), + "quoteDenoms": trading_reward_campaign_info.quote_denoms, + "tradingRewardBoostInfo": { + "boostedSpotMarketIds": ( + trading_reward_campaign_info.trading_reward_boost_info.boosted_spot_market_ids + ), + "spotMarketMultipliers": [ + { + "makerPointsMultiplier": spot_market_multiplier.maker_points_multiplier, + "takerPointsMultiplier": spot_market_multiplier.taker_points_multiplier, + }, + ], + "boostedDerivativeMarketIds": ( + trading_reward_campaign_info.trading_reward_boost_info.boosted_derivative_market_ids + ), + "derivativeMarketMultipliers": [ + { + "makerPointsMultiplier": derivative_market_multiplier.maker_points_multiplier, + "takerPointsMultiplier": derivative_market_multiplier.taker_points_multiplier, + }, + ], + }, + "disqualifiedMarketIds": trading_reward_campaign_info.disqualified_market_ids, + }, + "tradingRewardPoolCampaignSchedule": [ + { + "startTimestamp": str(trading_reward_pool_campaign_schedule.start_timestamp), + "maxCampaignRewards": [ + { + "amount": trading_reward_pool_campaign_schedule.max_campaign_rewards[0].amount, + "denom": trading_reward_pool_campaign_schedule.max_campaign_rewards[0].denom, + }, + ], + }, + ], + "totalTradeRewardPoints": total_trade_reward_points, + "pendingTradingRewardPoolCampaignSchedule": [ + { + "startTimestamp": str(pending_trading_reward_pool_campaign_schedule.start_timestamp), + "maxCampaignRewards": [ + { + "amount": pending_trading_reward_pool_campaign_schedule.max_campaign_rewards[0].amount, + "denom": pending_trading_reward_pool_campaign_schedule.max_campaign_rewards[0].denom, + }, + ], + }, + ], + "pendingTotalTradeRewardPoints": [pending_total_trade_reward_points], + } + + assert trade_reward_campaign == expected_campaign + + @pytest.mark.asyncio + async def test_fetch_fee_discount_account_info( + self, + exchange_servicer, + ): + account_info = exchange_pb.FeeDiscountTierInfo( + maker_discount_rate="0.0001", + taker_discount_rate="0.0002", + staked_amount="1000000000", + volume="1000000000000000000", + ) + account_ttl = exchange_pb.FeeDiscountTierTTL( + tier=3, + ttl_timestamp=1708099200, + ) + response = exchange_query_pb.QueryFeeDiscountAccountInfoResponse( + tier_level=3, + account_info=account_info, + account_ttl=account_ttl, + ) + exchange_servicer.fee_discount_account_info_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + fee_discount = await api.fetch_fee_discount_account_info(account="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r") + expected_fee_discount = { + "tierLevel": str(response.tier_level), + "accountInfo": { + "makerDiscountRate": account_info.maker_discount_rate, + "takerDiscountRate": account_info.taker_discount_rate, + "stakedAmount": account_info.staked_amount, + "volume": account_info.volume, + }, + "accountTtl": { + "tier": str(account_ttl.tier), + "ttlTimestamp": str(account_ttl.ttl_timestamp), + }, + } + + assert fee_discount == expected_fee_discount + + @pytest.mark.asyncio + async def test_fetch_fee_discount_schedule( + self, + exchange_servicer, + ): + fee_discount_tier_info = exchange_pb.FeeDiscountTierInfo( + maker_discount_rate="0.0001", + taker_discount_rate="0.0002", + staked_amount="1000000000", + volume="1000000000000000000", + ) + fee_discount_schedule = exchange_pb.FeeDiscountSchedule( + bucket_count=3, + bucket_duration=3600, + quote_denoms=["peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"], + tier_infos=[fee_discount_tier_info], + disqualified_market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"], + ) + exchange_servicer.fee_discount_schedule_responses.append( + exchange_query_pb.QueryFeeDiscountScheduleResponse( + fee_discount_schedule=fee_discount_schedule, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + schedule = await api.fetch_fee_discount_schedule() + expected_schedule = { + "feeDiscountSchedule": { + "bucketCount": str(fee_discount_schedule.bucket_count), + "bucketDuration": str(fee_discount_schedule.bucket_duration), + "quoteDenoms": fee_discount_schedule.quote_denoms, + "tierInfos": [ + { + "makerDiscountRate": fee_discount_tier_info.maker_discount_rate, + "takerDiscountRate": fee_discount_tier_info.taker_discount_rate, + "stakedAmount": fee_discount_tier_info.staked_amount, + "volume": fee_discount_tier_info.volume, + } + ], + "disqualifiedMarketIds": fee_discount_schedule.disqualified_market_ids, + }, + } + + assert schedule == expected_schedule + + @pytest.mark.asyncio + async def test_fetch_balance_mismatches( + self, + exchange_servicer, + ): + balance_mismatch = exchange_query_pb.BalanceMismatch( + subaccountId="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + available="1000000000000000", + total="2000000000000000", + balance_hold="3000000000000000", + expected_total="4000000000000000", + difference="500000000000000", + ) + exchange_servicer.balance_mismatches_responses.append( + exchange_query_pb.QueryBalanceMismatchesResponse( + balance_mismatches=[balance_mismatch], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + mismatches = await api.fetch_balance_mismatches(dust_factor=20) + expected_mismatches = { + "balanceMismatches": [ + { + "subaccountId": balance_mismatch.subaccountId, + "denom": balance_mismatch.denom, + "available": balance_mismatch.available, + "total": balance_mismatch.total, + "balanceHold": balance_mismatch.balance_hold, + "expectedTotal": balance_mismatch.expected_total, + "difference": balance_mismatch.difference, + } + ], + } + + assert mismatches == expected_mismatches + + @pytest.mark.asyncio + async def test_fetch_balance_with_balance_holds( + self, + exchange_servicer, + ): + balance_with_balance_hold = exchange_query_pb.BalanceWithMarginHold( + subaccountId="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + available="1000000000000000", + total="2000000000000000", + balance_hold="3000000000000000", + ) + exchange_servicer.balance_with_balance_holds_responses.append( + exchange_query_pb.QueryBalanceWithBalanceHoldsResponse( + balance_with_balance_holds=[balance_with_balance_hold], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + balance = await api.fetch_balance_with_balance_holds() + expected_balance = { + "balanceWithBalanceHolds": [ + { + "subaccountId": balance_with_balance_hold.subaccountId, + "denom": balance_with_balance_hold.denom, + "available": balance_with_balance_hold.available, + "total": balance_with_balance_hold.total, + "balanceHold": balance_with_balance_hold.balance_hold, + } + ], + } + + assert balance == expected_balance + + @pytest.mark.asyncio + async def test_fetch_fee_discount_tier_statistics( + self, + exchange_servicer, + ): + tier_statistics = exchange_query_pb.TierStatistic( + tier=3, + count=30, + ) + exchange_servicer.fee_discount_tier_statistics_responses.append( + exchange_query_pb.QueryFeeDiscountTierStatisticsResponse( + statistics=[tier_statistics], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + statistics = await api.fetch_fee_discount_tier_statistics() + expected_statistics = { + "statistics": [ + { + "tier": str(tier_statistics.tier), + "count": str(tier_statistics.count), + } + ], + } + + assert statistics == expected_statistics + + @pytest.mark.asyncio + async def test_fetch_mito_vault_infos( + self, + exchange_servicer, + ): + master_address = "inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9" + derivative_address = "inj1zlh5" + spot_address = "inj1zlh6" + cw20_address = "inj1zlh7" + response = exchange_query_pb.MitoVaultInfosResponse( + master_addresses=[master_address], + derivative_addresses=[derivative_address], + spot_addresses=[spot_address], + cw20_addresses=[cw20_address], + ) + exchange_servicer.mito_vault_infos_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + mito_vaults = await api.fetch_mito_vault_infos() + expected_mito_vaults = { + "masterAddresses": [master_address], + "derivativeAddresses": [derivative_address], + "spotAddresses": [spot_address], + "cw20Addresses": [cw20_address], + } + + assert mito_vaults == expected_mito_vaults + + @pytest.mark.asyncio + async def test_fetch_market_id_from_vault( + self, + exchange_servicer, + ): + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + exchange_servicer.market_id_from_vault_responses.append( + exchange_query_pb.QueryMarketIDFromVaultResponse( + market_id=market_id, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + market_id_response = await api.fetch_market_id_from_vault( + vault_address="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9" + ) + expected_market_id = { + "marketId": market_id, + } + + assert market_id_response == expected_market_id + + @pytest.mark.asyncio + async def test_fetch_historical_trade_records( + self, + exchange_servicer, + ): + latest_trade_record = exchange_pb.TradeRecord( + timestamp=1708099200, + price="2000000000000000000", + quantity="1000000000000000", + ) + trade_record = exchange_pb.TradeRecords( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + latest_trade_records=[latest_trade_record], + ) + exchange_servicer.historical_trade_records_responses.append( + exchange_query_pb.QueryHistoricalTradeRecordsResponse( + trade_records=[trade_record], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + records = await api.fetch_historical_trade_records(market_id=trade_record.market_id) + expected_records = { + "tradeRecords": [ + { + "marketId": trade_record.market_id, + "latestTradeRecords": [ + { + "timestamp": str(latest_trade_record.timestamp), + "price": latest_trade_record.price, + "quantity": latest_trade_record.quantity, + } + ], + }, + ], + } + + assert records == expected_records + + @pytest.mark.asyncio + async def test_fetch_is_opted_out_of_rewards( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryIsOptedOutOfRewardsResponse( + is_opted_out=False, + ) + exchange_servicer.is_opted_out_of_rewards_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + is_opted_out = await api.fetch_is_opted_out_of_rewards(account="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9") + expected_is_opted_out = { + "isOptedOut": response.is_opted_out, + } + + assert is_opted_out == expected_is_opted_out + + @pytest.mark.asyncio + async def test_fetch_opted_out_of_rewards_accounts( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryOptedOutOfRewardsAccountsResponse( + accounts=["inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9"], + ) + exchange_servicer.opted_out_of_rewards_accounts_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + opted_out = await api.fetch_opted_out_of_rewards_accounts() + expected_opted_out = { + "accounts": response.accounts, + } + + assert opted_out == expected_opted_out + + @pytest.mark.asyncio + async def test_fetch_market_volatility( + self, + exchange_servicer, + ): + history_metadata = oracle_pb.MetadataStatistics( + group_count=2, + records_sample_size=10, + mean="0.0001", + twap="0.0005", + first_timestamp=1702399200, + last_timestamp=1708099200, + min_price="1000000000000", + max_price="3000000000000", + median_price="2000000000000", + ) + trade_record = exchange_pb.TradeRecord( + timestamp=1708099200, + price="2000000000000000000", + quantity="1000000000000000", + ) + response = exchange_query_pb.QueryMarketVolatilityResponse( + volatility="0.0001", history_metadata=history_metadata, raw_history=[trade_record] + ) + exchange_servicer.market_volatility_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volatility = await api.fetch_market_volatility( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + trade_grouping_sec=0, + max_age=28000000, + include_raw_history=True, + include_metadata=True, + ) + expected_volatility = { + "volatility": response.volatility, + "historyMetadata": { + "groupCount": history_metadata.group_count, + "recordsSampleSize": history_metadata.records_sample_size, + "mean": history_metadata.mean, + "twap": history_metadata.twap, + "firstTimestamp": str(history_metadata.first_timestamp), + "lastTimestamp": str(history_metadata.last_timestamp), + "minPrice": history_metadata.min_price, + "maxPrice": history_metadata.max_price, + "medianPrice": history_metadata.median_price, + }, + "rawHistory": [ + { + "timestamp": str(trade_record.timestamp), + "price": trade_record.price, + "quantity": trade_record.quantity, + } + ], + } + + assert volatility == expected_volatility + + @pytest.mark.asyncio + async def test_fetch_binary_options_markets( + self, + exchange_servicer, + ): + market = exchange_pb.BinaryOptionsMarket( + ticker="20250608/USDT", + oracle_symbol="0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3", + oracle_provider="Pyth", + oracle_type=9, + oracle_scale_factor=6, + expiration_timestamp=1708099200, + settlement_timestamp=1707099200, + admin="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="400000000000000000", + status=1, + min_price_tick_size="100000000000000000000", + min_quantity_tick_size="1000000000000000", + settlement_price="2000000000000000000", + ) + response = exchange_query_pb.QueryBinaryMarketsResponse( + markets=[market], + ) + exchange_servicer.binary_options_markets_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + markets = await api.fetch_binary_options_markets(status="Active") + expected_markets = { + "markets": [ + { + "ticker": market.ticker, + "oracleSymbol": market.oracle_symbol, + "oracleProvider": market.oracle_provider, + "oracleType": oracle_pb.OracleType.Name(market.oracle_type), + "oracleScaleFactor": market.oracle_scale_factor, + "expirationTimestamp": str(market.expiration_timestamp), + "settlementTimestamp": str(market.settlement_timestamp), + "admin": market.admin, + "quoteDenom": market.quote_denom, + "marketId": market.market_id, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "status": exchange_pb.MarketStatus.Name(market.status), + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + "settlementPrice": market.settlement_price, + }, + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_trader_derivative_conditional_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeConditionalOrder( + price="2000000000000000000", + quantity="1000000000000000", + margin="2000000000000000000000000000000000", + triggerPrice="3000000000000000000", + isBuy=True, + isLimit=True, + order_hash="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + response = exchange_query_pb.QueryTraderDerivativeConditionalOrdersResponse(orders=[order]) + exchange_servicer.trader_derivative_conditional_orders_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_derivative_conditional_orders( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "triggerPrice": order.triggerPrice, + "isBuy": order.isBuy, + "isLimit": order.isLimit, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_market_atomic_execution_fee_multiplier( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryMarketAtomicExecutionFeeMultiplierResponse( + multiplier="100", + ) + exchange_servicer.market_atomic_execution_fee_multiplier_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + multiplier = await api.fetch_market_atomic_execution_fee_multiplier( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + expected_multiplier = { + "multiplier": response.multiplier, + } + + assert multiplier == expected_multiplier + + async def _dummy_metadata_provider(self): + return None diff --git a/tests/core/test_gas_limit_estimator.py b/tests/core/test_gas_limit_estimator.py index 916c47a9..293f5f25 100644 --- a/tests/core/test_gas_limit_estimator.py +++ b/tests/core/test_gas_limit_estimator.py @@ -24,26 +24,24 @@ def test_estimation_for_batch_create_spot_limit_orders(self): spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=5, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("5"), + quantity=Decimal("1"), + order_type="BUY", ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=4, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("4"), + quantity=Decimal("1"), + order_type="BUY", ), ] - message = composer.MsgBatchCreateSpotLimitOrders(sender="sender", orders=orders) + message = composer.msg_batch_create_spot_limit_orders(sender="sender", orders=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 50000 @@ -55,23 +53,23 @@ def test_estimation_for_batch_cancel_spot_orders(self): spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", ), ] - message = composer.MsgBatchCancelSpotOrders(sender="sender", data=orders) + message = composer.msg_batch_cancel_spot_orders(sender="sender", orders_data=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 50000 @@ -83,28 +81,26 @@ def test_estimation_for_batch_create_derivative_limit_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=3, - quantity=1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(3), + quantity=Decimal(1), + margin=Decimal(3), + order_type="BUY", ), - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=20, - quantity=1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(20), + quantity=Decimal(1), + margin=Decimal(20), + order_type="SELL", ), ] - message = composer.MsgBatchCreateDerivativeLimitOrders(sender="sender", orders=orders) + message = composer.msg_batch_create_derivative_limit_orders(sender="sender", orders=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 70_000 @@ -116,23 +112,23 @@ def test_estimation_for_batch_cancel_derivative_orders(self): spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", ), ] - message = composer.MsgBatchCancelDerivativeOrders(sender="sender", data=orders) + message = composer.msg_batch_cancel_derivative_orders(sender="sender", orders_data=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 60_000 @@ -144,23 +140,21 @@ def test_estimation_for_batch_update_orders_to_create_spot_orders(self): market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.SpotOrder( + composer.spot_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=5, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("5"), + quantity=Decimal("1"), + order_type="BUY", ), - composer.SpotOrder( + composer.spot_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=4, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("4"), + quantity=Decimal("1"), + order_type="BUY", ), ] message = composer.MsgBatchUpdateOrders( @@ -181,25 +175,23 @@ def test_estimation_for_batch_update_orders_to_create_derivative_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=3, - quantity=1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(3), + quantity=Decimal(1), + margin=Decimal(3), + order_type="BUY", ), - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=20, - quantity=1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(20), + quantity=Decimal(1), + margin=Decimal(20), + order_type="SELL", ), ] message = composer.MsgBatchUpdateOrders( @@ -238,25 +230,23 @@ def test_estimation_for_batch_update_orders_to_create_binary_orders(self, usdt_t ) composer.binary_option_markets[market.id] = market orders = [ - composer.BinaryOptionsOrder( + composer.binary_options_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=3, - quantity=1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(3), + quantity=Decimal(1), + margin=Decimal(3), + order_type="BUY", ), - composer.BinaryOptionsOrder( + composer.binary_options_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=20, - quantity=1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(20), + quantity=Decimal(1), + margin=Decimal(20), + order_type="SELL", ), ] message = composer.MsgBatchUpdateOrders( @@ -278,17 +268,17 @@ def test_estimation_for_batch_update_orders_to_cancel_spot_orders(self): market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -312,17 +302,17 @@ def test_estimation_for_batch_update_orders_to_cancel_derivative_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -346,17 +336,17 @@ def test_estimation_for_batch_update_orders_to_cancel_binary_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -441,14 +431,13 @@ def test_estimation_for_exec_message(self): market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.SpotOrder( + composer.spot_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=5, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("5"), + quantity=Decimal("1"), + order_type="BUY", ), ] inner_message = composer.MsgBatchUpdateOrders( @@ -510,15 +499,14 @@ def test_estimation_for_governance_message(self): def test_estimation_for_generic_exchange_message(self): composer = Composer(network="testnet") - message = composer.MsgCreateSpotLimitOrder( + message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) estimator = GasLimitEstimator.for_message(message=message) diff --git a/tests/core/test_market.py b/tests/core/test_market.py index ede8aea5..48c2f5e5 100644 --- a/tests/core/test_market.py +++ b/tests/core/test_market.py @@ -248,6 +248,42 @@ def test_convert_price_to_chain_format_without_fixed_denom(self, first_match_bet assert quantized_chain_format_value == chain_value + def test_convert_margin_to_chain_format_with_fixed_denom(self, first_match_bet_market: BinaryOptionMarket): + original_quantity = Decimal("123.456789") + fixed_denom = Denom( + description="Fixed denom", + base=2, + quote=4, + min_quantity_tick_size=100, + min_price_tick_size=10000, + ) + + chain_value = first_match_bet_market.margin_to_chain_format( + human_readable_value=original_quantity, + special_denom=fixed_denom, + ) + price_decimals = fixed_denom.quote + expected_value = original_quantity * Decimal(f"1e{price_decimals}") + quantized_value = (expected_value // Decimal(str(fixed_denom.min_quantity_tick_size))) * Decimal( + str(fixed_denom.min_quantity_tick_size) + ) + quantized_chain_format_value = quantized_value * Decimal("1e18") + + assert quantized_chain_format_value == chain_value + + def test_convert_margin_to_chain_format_without_fixed_denom(self, first_match_bet_market: BinaryOptionMarket): + original_quantity = Decimal("123.456789") + + chain_value = first_match_bet_market.margin_to_chain_format(human_readable_value=original_quantity) + price_decimals = first_match_bet_market.quote_token.decimals + expected_value = original_quantity * Decimal(f"1e{price_decimals}") + quantized_value = ( + expected_value // first_match_bet_market.min_quantity_tick_size + ) * first_match_bet_market.min_quantity_tick_size + quantized_chain_format_value = quantized_value * Decimal("1e18") + + assert quantized_chain_format_value == chain_value + def test_calculate_margin_for_buy_with_fixed_denom(self, first_match_bet_market: BinaryOptionMarket): original_quantity = Decimal("123.456789") original_price = Decimal("0.6789") diff --git a/tests/core/test_message_based_transaction_fee_calculator.py b/tests/core/test_message_based_transaction_fee_calculator.py index 23e263c9..b1d774e0 100644 --- a/tests/core/test_message_based_transaction_fee_calculator.py +++ b/tests/core/test_message_based_transaction_fee_calculator.py @@ -117,15 +117,14 @@ async def test_gas_fee_for_exchange_message(self): gas_price=5_000_000, ) - message = composer.MsgCreateSpotLimitOrder( + message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) transaction = Transaction() transaction.with_messages(message) @@ -148,15 +147,14 @@ async def test_gas_fee_for_msg_exec_message(self): gas_price=5_000_000, ) - inner_message = composer.MsgCreateSpotLimitOrder( + inner_message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) message = composer.MsgExec(grantee="grantee", msgs=[inner_message]) transaction = Transaction() @@ -184,15 +182,14 @@ async def test_gas_fee_for_two_messages_in_one_transaction(self): gas_price=5_000_000, ) - inner_message = composer.MsgCreateSpotLimitOrder( + inner_message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) message = composer.MsgExec(grantee="grantee", msgs=[inner_message]) diff --git a/tests/test_async_client_deprecation_warnings.py b/tests/test_async_client_deprecation_warnings.py index dae2d807..1df77fe8 100644 --- a/tests/test_async_client_deprecation_warnings.py +++ b/tests/test_async_client_deprecation_warnings.py @@ -21,7 +21,7 @@ from pyinjective.proto.injective.stream.v1beta1 import query_pb2 as chain_stream_pb from pyinjective.proto.injective.types.v1beta1 import account_pb2 as account_pb from tests.client.chain.grpc.configurable_auth_query_servicer import ConfigurableAuthQueryServicer -from tests.client.chain.grpc.configurable_autz_query_servicer import ConfigurableAuthZQueryServicer +from tests.client.chain.grpc.configurable_authz_query_servicer import ConfigurableAuthZQueryServicer from tests.client.chain.grpc.configurable_bank_query_servicer import ConfigurableBankQueryServicer from tests.client.chain.stream_grpc.configurable_chain_stream_query_servicer import ConfigurableChainStreamQueryServicer from tests.client.indexer.configurable_account_query_servicer import ConfigurableAccountQueryServicer diff --git a/tests/test_composer.py b/tests/test_composer.py index 4f756c79..2dcbd056 100644 --- a/tests/test_composer.py +++ b/tests/test_composer.py @@ -2,12 +2,11 @@ from decimal import Decimal import pytest +from google.protobuf import json_format from pyinjective.composer import Composer -from pyinjective.core.market import BinaryOptionMarket, DerivativeMarket, SpotMarket +from pyinjective.constant import ADDITIONAL_CHAIN_FORMAT_DECIMALS from pyinjective.core.network import Network -from pyinjective.proto.injective.exchange.v1beta1 import exchange_pb2 -from pyinjective.utils.denom import Denom from tests.model_fixtures.markets_fixtures import btc_usdt_perp_market # noqa: F401 from tests.model_fixtures.markets_fixtures import first_match_bet_market # noqa: F401 from tests.model_fixtures.markets_fixtures import inj_token # noqa: F401 @@ -57,211 +56,6 @@ def test_composer_initialization_from_ini_files(self): assert 6 == inj_usdt_spot_market.quote_token.decimals assert 6 == inj_usdt_perp_market.quote_token.decimals - def test_buy_spot_order_creation(self, basic_composer: Composer, inj_usdt_spot_market: SpotMarket): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - order = basic_composer.SpotOrder( - market_id=inj_usdt_spot_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - ) - - price_decimals = inj_usdt_spot_market.quote_token.decimals - inj_usdt_spot_market.base_token.decimals - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // inj_usdt_spot_market.min_price_tick_size) - * inj_usdt_spot_market.min_price_tick_size - * Decimal("1e18") - ) - chain_format_quantity = Decimal(str(quantity)) * Decimal(f"1e{inj_usdt_spot_market.base_token.decimals}") - expected_quantity = ( - (chain_format_quantity // inj_usdt_spot_market.min_quantity_tick_size) - * inj_usdt_spot_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert order.market_id == inj_usdt_spot_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.trigger_price == "0" - - def test_buy_derivative_order_creation(self, basic_composer: Composer, btc_usdt_perp_market: DerivativeMarket): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - leverage = 2 - order = basic_composer.DerivativeOrder( - market_id=btc_usdt_perp_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - leverage=leverage, - ) - - price_decimals = btc_usdt_perp_market.quote_token.decimals - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // btc_usdt_perp_market.min_price_tick_size) - * btc_usdt_perp_market.min_price_tick_size - * Decimal("1e18") - ) - chain_format_quantity = Decimal(str(quantity)) - expected_quantity = ( - (chain_format_quantity // btc_usdt_perp_market.min_quantity_tick_size) - * btc_usdt_perp_market.min_quantity_tick_size - * Decimal("1e18") - ) - chain_format_margin = (chain_format_quantity * chain_format_price) / Decimal(leverage) - expected_margin = ( - (chain_format_margin // btc_usdt_perp_market.min_quantity_tick_size) - * btc_usdt_perp_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert order.market_id == btc_usdt_perp_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.margin == str(int(expected_margin)) - assert order.trigger_price == "0" - - def test_increase_position_margin(self, basic_composer: Composer, btc_usdt_perp_market: DerivativeMarket): - sender = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - amount = 1587.789 - message = basic_composer.MsgIncreasePositionMargin( - sender=sender, - source_subaccount_id="1", - destination_subaccount_id="2", - market_id=btc_usdt_perp_market.id, - amount=amount, - ) - - price_decimals = btc_usdt_perp_market.quote_token.decimals - chain_format_margin = Decimal(str(amount)) * Decimal(f"1e{price_decimals}") - expected_margin = ( - (chain_format_margin // btc_usdt_perp_market.min_quantity_tick_size) - * btc_usdt_perp_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert message.market_id == btc_usdt_perp_market.id - assert message.sender == sender - assert message.source_subaccount_id == "1" - assert message.destination_subaccount_id == "2" - assert message.amount == str(int(expected_margin)) - - def test_buy_binary_option_order_creation_with_fixed_denom( - self, basic_composer: Composer, first_match_bet_market: BinaryOptionMarket - ): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - fixed_denom = Denom( - description="Fixed denom", - base=2, - quote=6, - min_price_tick_size=1000, - min_quantity_tick_size=10000, - ) - - order = basic_composer.BinaryOptionsOrder( - market_id=first_match_bet_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - denom=fixed_denom, - ) - - price_decimals = fixed_denom.quote - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // Decimal(str(fixed_denom.min_price_tick_size))) - * Decimal(str(fixed_denom.min_price_tick_size)) - * Decimal("1e18") - ) - quantity_decimals = fixed_denom.base - chain_format_quantity = Decimal(str(quantity)) * Decimal(f"1e{quantity_decimals}") - expected_quantity = ( - (chain_format_quantity // Decimal(str(fixed_denom.min_quantity_tick_size))) - * Decimal(str(fixed_denom.min_quantity_tick_size)) - * Decimal("1e18") - ) - chain_format_margin = chain_format_quantity * chain_format_price - expected_margin = ( - (chain_format_margin // Decimal(str(fixed_denom.min_quantity_tick_size))) - * Decimal(str(fixed_denom.min_quantity_tick_size)) - * Decimal("1e18") - ) - - assert order.market_id == first_match_bet_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.margin == str(int(expected_margin)) - assert order.trigger_price == "0" - - def test_buy_binary_option_order_creation_without_fixed_denom( - self, - basic_composer: Composer, - first_match_bet_market: BinaryOptionMarket, - ): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - - order = basic_composer.BinaryOptionsOrder( - market_id=first_match_bet_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - ) - - price_decimals = first_match_bet_market.quote_token.decimals - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // first_match_bet_market.min_price_tick_size) - * first_match_bet_market.min_price_tick_size - * Decimal("1e18") - ) - chain_format_quantity = Decimal(str(quantity)) - expected_quantity = ( - (chain_format_quantity // first_match_bet_market.min_quantity_tick_size) - * first_match_bet_market.min_quantity_tick_size - * Decimal("1e18") - ) - chain_format_margin = chain_format_quantity * chain_format_price - expected_margin = ( - (chain_format_margin // first_match_bet_market.min_quantity_tick_size) - * first_match_bet_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert order.market_id == first_match_bet_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.margin == str(int(expected_margin)) - assert order.trigger_price == "0" - def test_msg_create_denom(self, basic_composer: Composer): sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" subdenom = "inj-test" @@ -282,7 +76,7 @@ def test_msg_create_denom(self, basic_composer: Composer): def test_msg_mint(self, basic_composer: Composer): sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" - amount = basic_composer.Coin( + amount = basic_composer.coin( amount=1_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test", ) @@ -297,7 +91,7 @@ def test_msg_mint(self, basic_composer: Composer): def test_msg_burn(self, basic_composer: Composer): sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" - amount = basic_composer.Coin( + amount = basic_composer.coin( amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test", ) @@ -380,3 +174,1259 @@ def test_msg_execute_contract_compat(self, basic_composer): assert message.contract == contract assert message.msg == msg assert message.funds == funds + + def test_msg_deposit(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=Decimal(amount)) + + message = basic_composer.msg_deposit( + sender=sender, + subaccount_id=subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_withdraw(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=Decimal(amount)) + + message = basic_composer.msg_withdraw( + sender=sender, + subaccount_id=subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_spot_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "INJ/USDT" + base_denom = "INJ" + quote_denom = "USDT" + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + + base_token = basic_composer.tokens[base_denom] + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals - base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal( + f"1e{base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + + message = basic_composer.msg_instant_spot_market_launch( + sender=sender, + ticker=ticker, + base_denom=base_denom, + quote_denom=quote_denom, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "baseDenom": base_token.denom, + "quoteDenom": quote_token.denom, + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_perpetual_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "BTC/INJ PERP" + quote_denom = "INJ" + oracle_base = "BTC" + oracle_quote = "INJ" + oracle_scale_factor = 6 + oracle_type = "Band" + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + maker_fee_rate = Decimal("0.001") + taker_fee_rate = Decimal("-0.002") + initial_margin_ratio = Decimal("0.05") + maintenance_margin_ratio = Decimal("0.03") + + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + message = basic_composer.msg_instant_perpetual_market_launch( + sender=sender, + ticker=ticker, + quote_denom=quote_denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=oracle_type, + maker_fee_rate=maker_fee_rate, + taker_fee_rate=taker_fee_rate, + initial_margin_ratio=initial_margin_ratio, + maintenance_margin_ratio=maintenance_margin_ratio, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "quoteDenom": quote_token.denom, + "oracleBase": oracle_base, + "oracleQuote": oracle_quote, + "oracleScaleFactor": oracle_scale_factor, + "oracleType": oracle_type, + "makerFeeRate": f"{expected_maker_fee_rate.normalize():f}", + "takerFeeRate": f"{expected_taker_fee_rate.normalize():f}", + "initialMarginRatio": f"{expected_initial_margin_ratio.normalize():f}", + "maintenanceMarginRatio": f"{expected_maintenance_margin_ratio.normalize():f}", + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_expiry_futures_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "BTC/INJ PERP" + quote_denom = "INJ" + oracle_base = "BTC" + oracle_quote = "INJ" + oracle_scale_factor = 6 + oracle_type = "Band" + expiry = 1630000000 + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + maker_fee_rate = Decimal("0.001") + taker_fee_rate = Decimal("-0.002") + initial_margin_ratio = Decimal("0.05") + maintenance_margin_ratio = Decimal("0.03") + + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + message = basic_composer.msg_instant_expiry_futures_market_launch( + sender=sender, + ticker=ticker, + quote_denom=quote_denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=oracle_type, + expiry=expiry, + maker_fee_rate=maker_fee_rate, + taker_fee_rate=taker_fee_rate, + initial_margin_ratio=initial_margin_ratio, + maintenance_margin_ratio=maintenance_margin_ratio, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "quoteDenom": quote_token.denom, + "oracleBase": oracle_base, + "oracleQuote": oracle_quote, + "oracleType": oracle_type, + "oracleScaleFactor": oracle_scale_factor, + "expiry": str(expiry), + "makerFeeRate": f"{expected_maker_fee_rate.normalize():f}", + "takerFeeRate": f"{expected_taker_fee_rate.normalize():f}", + "initialMarginRatio": f"{expected_initial_margin_ratio.normalize():f}", + "maintenanceMarginRatio": f"{expected_maintenance_margin_ratio.normalize():f}", + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_spot_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.spot_order( + market_id=spot_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = spot_market.price_to_chain_format(human_readable_value=price) + expected_quantity = spot_market.quantity_to_chain_format(human_readable_value=quantity) + expected_trigger_price = spot_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_order = { + "marketId": spot_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=order, + including_default_value_fields=True, + ) + assert dict_message == expected_order + + def test_derivative_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.derivative_order( + market_id=derivative_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = derivative_market.price_to_chain_format(human_readable_value=price) + expected_quantity = derivative_market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = derivative_market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = derivative_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_order = { + "marketId": derivative_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "margin": f"{expected_margin.normalize():f}", + "triggerPrice": f"{expected_trigger_price.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=order, + including_default_value_fields=True, + ) + assert dict_message == expected_order + + def test_msg_create_spot_limit_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_spot_limit_order( + market_id=spot_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = spot_market.price_to_chain_format(human_readable_value=price) + expected_quantity = spot_market.quantity_to_chain_format(human_readable_value=quantity) + expected_trigger_price = spot_market.price_to_chain_format(human_readable_value=trigger_price) + + assert "injective.exchange.v1beta1.MsgCreateSpotLimitOrder" == message.DESCRIPTOR.full_name + expected_message = { + "sender": sender, + "order": { + "marketId": spot_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_create_spot_limit_orders(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.spot_order( + market_id=spot_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + message = basic_composer.msg_batch_create_spot_limit_orders( + sender=sender, + orders=[order], + ) + + expected_message = { + "sender": sender, + "orders": [json_format.MessageToDict(message=order, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_spot_market_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_spot_market_order( + market_id=spot_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = spot_market.price_to_chain_format(human_readable_value=price) + expected_quantity = spot_market.quantity_to_chain_format(human_readable_value=quantity) + expected_trigger_price = spot_market.price_to_chain_format(human_readable_value=trigger_price) + + assert "injective.exchange.v1beta1.MsgCreateSpotMarketOrder" == message.DESCRIPTOR.full_name + expected_message = { + "sender": sender, + "order": { + "marketId": spot_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_cancel_spot_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + order_hash = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + cid = "test_cid" + + message = basic_composer.msg_cancel_spot_order( + market_id=spot_market.id, + sender=sender, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + ) + + expected_message = { + "sender": sender, + "marketId": spot_market.id, + "subaccountId": subaccount_id, + "orderHash": order_hash, + "cid": cid, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_cancel_spot_orders(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + + order_data = basic_composer.order_data( + market_id=spot_market.id, + subaccount_id=subaccount_id, + order_hash="0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000", + ) + + message = basic_composer.msg_batch_cancel_spot_orders( + sender=sender, + orders_data=[order_data], + ) + + assert "injective.exchange.v1beta1.MsgBatchCancelSpotOrders" == message.DESCRIPTOR.full_name + expected_message = { + "sender": sender, + "data": [json_format.MessageToDict(message=order_data, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_update_orders(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + derivative_market = list(basic_composer.derivative_markets.values())[0] + binary_options_market = list(basic_composer.binary_option_markets.values())[0] + + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + spot_market_id = spot_market.id + derivative_market_id = derivative_market.id + binary_options_market_id = binary_options_market.id + spot_order_to_cancel = basic_composer.order_data( + market_id=spot_market_id, + subaccount_id=subaccount_id, + order_hash="0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000", + ) + derivative_order_to_cancel = basic_composer.order_data( + market_id=derivative_market_id, + subaccount_id=subaccount_id, + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", + ) + binary_options_order_to_cancel = basic_composer.order_data( + market_id=binary_options_market_id, + subaccount_id=subaccount_id, + order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", + ) + spot_order_to_create = basic_composer.spot_order( + market_id=spot_market_id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + order_type="BUY", + cid="test_cid", + trigger_price=Decimal("43.5"), + ) + derivative_order_to_create = basic_composer.derivative_order( + market_id=derivative_market_id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + margin=Decimal("36.1") * Decimal("100"), + order_type="BUY", + ) + binary_options_order_to_create = basic_composer.binary_options_order( + market_id=binary_options_market_id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + margin=Decimal("36.1") * Decimal("100"), + order_type="BUY", + ) + + message = basic_composer.msg_batch_update_orders( + sender=sender, + subaccount_id=subaccount_id, + spot_market_ids_to_cancel_all=[spot_market_id], + derivative_market_ids_to_cancel_all=[derivative_market_id], + spot_orders_to_cancel=[spot_order_to_cancel], + derivative_orders_to_cancel=[derivative_order_to_cancel], + spot_orders_to_create=[spot_order_to_create], + derivative_orders_to_create=[derivative_order_to_create], + binary_options_orders_to_cancel=[binary_options_order_to_cancel], + binary_options_market_ids_to_cancel_all=[binary_options_market_id], + binary_options_orders_to_create=[binary_options_order_to_create], + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "spotMarketIdsToCancelAll": [spot_market_id], + "derivativeMarketIdsToCancelAll": [derivative_market_id], + "spotOrdersToCancel": [ + json_format.MessageToDict(message=spot_order_to_cancel, including_default_value_fields=True) + ], + "derivativeOrdersToCancel": [ + json_format.MessageToDict(message=derivative_order_to_cancel, including_default_value_fields=True) + ], + "spotOrdersToCreate": [ + json_format.MessageToDict(message=spot_order_to_create, including_default_value_fields=True) + ], + "derivativeOrdersToCreate": [ + json_format.MessageToDict(message=derivative_order_to_create, including_default_value_fields=True) + ], + "binaryOptionsOrdersToCancel": [ + json_format.MessageToDict(message=binary_options_order_to_cancel, including_default_value_fields=True) + ], + "binaryOptionsMarketIdsToCancelAll": [binary_options_market_id], + "binaryOptionsOrdersToCreate": [ + json_format.MessageToDict(message=binary_options_order_to_create, including_default_value_fields=True) + ], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_privileged_execute_contract(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + contract_address = "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7" + data = "test_data" + funds = "100inj,420peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7" + + message = basic_composer.msg_privileged_execute_contract( + sender=sender, + contract_address=contract_address, + data=data, + funds=funds, + ) + + expected_message = { + "sender": sender, + "funds": funds, + "contractAddress": contract_address, + "data": data, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_derivative_limit_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_derivative_limit_order( + market_id=derivative_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = derivative_market.price_to_chain_format(human_readable_value=price) + expected_quantity = derivative_market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = derivative_market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = derivative_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": derivative_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_create_derivative_limit_orders(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.derivative_order( + market_id=derivative_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=price * quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + message = basic_composer.msg_batch_create_derivative_limit_orders( + sender=sender, + orders=[order], + ) + + expected_message = { + "sender": sender, + "orders": [json_format.MessageToDict(message=order, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_derivative_market_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_derivative_market_order( + market_id=derivative_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = derivative_market.price_to_chain_format(human_readable_value=price) + expected_quantity = derivative_market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = derivative_market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = derivative_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": derivative_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_cancel_derivative_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + order_hash = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + cid = "test_cid" + is_conditional = False + is_buy = True + is_market_order = False + + expected_order_mask = basic_composer._order_mask( + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + message = basic_composer.msg_cancel_derivative_order( + market_id=derivative_market.id, + sender=sender, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + expected_message = { + "sender": sender, + "marketId": derivative_market.id, + "subaccountId": subaccount_id, + "orderHash": order_hash, + "orderMask": expected_order_mask, + "cid": cid, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_cancel_derivative_orders(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + + order_data = basic_composer.order_data( + market_id=derivative_market.id, + subaccount_id=subaccount_id, + order_hash="0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000", + ) + + message = basic_composer.msg_batch_cancel_derivative_orders( + sender=sender, + orders_data=[order_data], + ) + + expected_message = { + "sender": sender, + "data": [json_format.MessageToDict(message=order_data, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_binary_options_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "B2500/INJ" + oracle_symbol = "B2500_1/INJ" + oracle_provider = "Injective" + oracle_scale_factor = 6 + oracle_type = "Band" + quote_denom = "INJ" + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + maker_fee_rate = Decimal("0.001") + taker_fee_rate = Decimal("-0.002") + expiration_timestamp = 1630000000 + settlement_timestamp = 1660000000 + admin = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + message = basic_composer.msg_instant_binary_options_market_launch( + sender=sender, + ticker=ticker, + oracle_symbol=oracle_symbol, + oracle_provider=oracle_provider, + oracle_type=oracle_type, + oracle_scale_factor=oracle_scale_factor, + maker_fee_rate=maker_fee_rate, + taker_fee_rate=taker_fee_rate, + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + admin=admin, + quote_denom=quote_denom, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "oracleSymbol": oracle_symbol, + "oracleProvider": oracle_provider, + "oracleType": oracle_type, + "oracleScaleFactor": oracle_scale_factor, + "makerFeeRate": f"{expected_maker_fee_rate.normalize():f}", + "takerFeeRate": f"{expected_taker_fee_rate.normalize():f}", + "expirationTimestamp": str(expiration_timestamp), + "settlementTimestamp": str(settlement_timestamp), + "admin": admin, + "quoteDenom": quote_token.denom, + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_binary_options_limit_order(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_binary_options_limit_order( + market_id=market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = market.price_to_chain_format(human_readable_value=price) + expected_quantity = market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_binary_options_market_order(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_binary_options_market_order( + market_id=market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = market.price_to_chain_format(human_readable_value=price) + expected_quantity = market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_cancel_derivative_order(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + order_hash = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + cid = "test_cid" + is_conditional = False + is_buy = True + is_market_order = False + + expected_order_mask = basic_composer._order_mask( + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + message = basic_composer.msg_cancel_derivative_order( + market_id=market.id, + sender=sender, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + expected_message = { + "sender": sender, + "marketId": market.id, + "subaccountId": subaccount_id, + "orderHash": order_hash, + "orderMask": expected_order_mask, + "cid": cid, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_subaccount_transfer(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + source_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + destination_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000002" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=amount) + + message = basic_composer.msg_subaccount_transfer( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "sourceSubaccountId": source_subaccount_id, + "destinationSubaccountId": destination_subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_external_transfer(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + source_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + destination_subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=amount) + + message = basic_composer.msg_subaccount_transfer( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "sourceSubaccountId": source_subaccount_id, + "destinationSubaccountId": destination_subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_liquidate_position(self, basic_composer): + market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + order = basic_composer.derivative_order( + market_id=market.id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + margin=Decimal("36.1") * Decimal("100"), + order_type="BUY", + ) + + message = basic_composer.msg_liquidate_position( + sender=sender, + subaccount_id=subaccount_id, + market_id=market.id, + order=order, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "marketId": market.id, + "order": json_format.MessageToDict(message=order, including_default_value_fields=True), + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_emergency_settle_market(self, basic_composer): + market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + + message = basic_composer.msg_emergency_settle_market( + sender=sender, + subaccount_id=subaccount_id, + market_id=market.id, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "marketId": market.id, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_external_transfer(self, basic_composer): + market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + source_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + destination_subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000" + amount = Decimal(100) + + expected_amount = market.margin_to_chain_format(human_readable_value=amount) + + message = basic_composer.msg_increase_position_margin( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + market_id=market.id, + amount=amount, + ) + + expected_message = { + "sender": sender, + "sourceSubaccountId": source_subaccount_id, + "destinationSubaccountId": destination_subaccount_id, + "marketId": market.id, + "amount": f"{expected_amount.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_rewards_opt_out(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + + message = basic_composer.msg_rewards_opt_out( + sender=sender, + ) + + expected_message = { + "sender": sender, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_admin_update_binary_options_market(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + status = "Paused" + settlement_price = Decimal("100.5") + expiration_timestamp = 1630000000 + settlement_timestamp = 1660000000 + + expected_settlement_price = market.price_to_chain_format(human_readable_value=settlement_price) + + message = basic_composer.msg_admin_update_binary_options_market( + sender=sender, + market_id=market.id, + status=status, + settlement_price=settlement_price, + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + ) + + expected_message = { + "sender": sender, + "marketId": market.id, + "settlementPrice": f"{expected_settlement_price.normalize():f}", + "expirationTimestamp": str(expiration_timestamp), + "settlementTimestamp": str(settlement_timestamp), + "status": status, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message diff --git a/tests/test_composer_deprecation_warnings.py b/tests/test_composer_deprecation_warnings.py new file mode 100644 index 00000000..20a86779 --- /dev/null +++ b/tests/test_composer_deprecation_warnings.py @@ -0,0 +1,522 @@ +import warnings +from decimal import Decimal + +import pytest + +from pyinjective.composer import Composer +from pyinjective.core.network import Network +from tests.model_fixtures.markets_fixtures import btc_usdt_perp_market # noqa: F401 +from tests.model_fixtures.markets_fixtures import first_match_bet_market # noqa: F401 +from tests.model_fixtures.markets_fixtures import inj_token # noqa: F401 +from tests.model_fixtures.markets_fixtures import inj_usdt_spot_market # noqa: F401 +from tests.model_fixtures.markets_fixtures import usdt_perp_token # noqa: F401 +from tests.model_fixtures.markets_fixtures import usdt_token # noqa: F401 + + +class TestComposerDeprecationWarnings: + @pytest.fixture + def basic_composer(self, inj_usdt_spot_market, btc_usdt_perp_market, first_match_bet_market): + composer = Composer( + network=Network.devnet().string(), + spot_markets={inj_usdt_spot_market.id: inj_usdt_spot_market}, + derivative_markets={btc_usdt_perp_market.id: btc_usdt_perp_market}, + binary_option_markets={first_match_bet_market.id: first_match_bet_market}, + tokens={ + inj_usdt_spot_market.base_token.symbol: inj_usdt_spot_market.base_token, + inj_usdt_spot_market.quote_token.symbol: inj_usdt_spot_market.quote_token, + btc_usdt_perp_market.quote_token.symbol: btc_usdt_perp_market.quote_token, + }, + ) + + return composer + + def test_msg_deposit_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgDeposit(sender="sender", subaccount_id="subaccount id", amount=1, denom="INJ") + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_deposit instead" + + def test_msg_withdraw_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgWithdraw(sender="sender", subaccount_id="subaccount id", amount=1, denom="USDT") + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_withdraw instead" + + def teste_order_data_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.OrderData( + market_id="market id", + subaccount_id="subaccount id", + order_hash="order hash", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use order_data instead" + + def test_spot_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.SpotOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + is_buy=True, + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use spot_order instead" + + def test_derivative_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.DerivativeOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + is_buy=True, + cid="cid", + leverage=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use derivative_order instead" + + def test_msg_create_spot_limit_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateSpotLimitOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_create_spot_limit_order instead" + ) + + def test_msg_batch_create_spot_limit_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + order = composer.spot_order( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=Decimal(1), + quantity=Decimal(1), + order_type="BUY", + ) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCreateSpotLimitOrders( + sender="sender", + orders=[order], + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_create_spot_limit_orders instead" + ) + + def test_msg_create_spot_market_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateSpotMarketOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + is_buy=True, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_spot_market_order instead" + ) + + def test_msg_cancel_spot_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCancelSpotOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + sender="sender", + subaccount_id="subaccount id", + order_hash="order hash", + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_cancel_spot_order instead" + + def test_msg_batch_cancel_spot_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + orders = [ + composer.order_data( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", + ), + ] + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCancelSpotOrders(sender="sender", data=orders) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_cancel_spot_orders instead" + ) + + def test_msg_batch_update_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchUpdateOrders(sender="sender") + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_batch_update_orders instead" + + def test_msg_privileged_execute_contract_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgPrivilegedExecuteContract( + sender="sender", + contract="contract", + msg="msg", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_privileged_execute_contract instead" + ) + + def test_msg_create_derivative_limit_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateDerivativeLimitOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + leverage=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_derivative_limit_order instead" + ) + + def test_msg_batch_create_derivative_limit_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + order = composer.derivative_order( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=Decimal(1), + quantity=Decimal(1), + margin=Decimal(1), + order_type="BUY", + ) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCreateDerivativeLimitOrders( + sender="sender", + orders=[order], + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_create_derivative_limit_orders instead" + ) + + def test_msg_create_derivative_market_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateDerivativeMarketOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + leverage=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_derivative_market_order instead" + ) + + def test_msg_cancel_derivative_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCancelDerivativeOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + sender="sender", + subaccount_id="subaccount id", + order_hash="order hash", + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_cancel_derivative_order instead" + ) + + def test_msg_batch_cancel_derivative_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + orders = [ + composer.order_data( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", + ), + ] + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCancelDerivativeOrders(sender="sender", data=orders) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_cancel_derivative_orders instead" + ) + + def test_msg_instant_binary_options_market_launch_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgInstantBinaryOptionsMarketLaunch( + sender="sender", + ticker="B2400/INJ", + oracle_symbol="B2400/INJ", + oracle_provider="injective", + oracle_type="Band", + oracle_scale_factor=6, + maker_fee_rate=0.001, + taker_fee_rate=0.001, + expiration_timestamp=1630000000, + settlement_timestamp=1630000000, + quote_denom="inj", + quote_decimals=18, + min_price_tick_size=0.01, + min_quantity_tick_size=0.01, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_instant_binary_options_market_launch instead" + ) + + def test_msg_create_binary_options_limit_order_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgCreateBinaryOptionsLimitOrder( + market_id=market.id, + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + is_buy=True, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_binary_options_limit_order instead" + ) + + def test_msg_create_binary_options_market_order_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgCreateBinaryOptionsMarketOrder( + market_id=market.id, + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + is_buy=True, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_binary_options_market_order instead" + ) + + def test_msg_cancel_binary_options_order_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgCancelBinaryOptionsOrder( + market_id=market.id, + sender="sender", + subaccount_id="subaccount id", + order_hash="order hash", + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_cancel_binary_options_order instead" + ) + + def test_msg_subaccount_transfer_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgSubaccountTransfer( + sender="sender", + source_subaccount_id="source subaccount id", + destination_subaccount_id="destination subaccount id", + amount=1, + denom="INJ", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_subaccount_transfer instead" + + def test_msg_external_transfer_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgExternalTransfer( + sender="sender", + source_subaccount_id="source subaccount id", + destination_subaccount_id="destination subaccount id", + amount=1, + denom="INJ", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_external_transfer instead" + + def test_msg_liquidate_position_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgLiquidatePosition( + sender="sender", + subaccount_id="subaccount id", + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_liquidate_position instead" + + def test_msg_increase_position_margin_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgIncreasePositionMargin( + sender="sender", + source_subaccount_id="source_subaccount id", + destination_subaccount_id="destination_subaccount id", + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + amount=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_increase_position_margin instead" + ) + + def test_msg_rewards_opt_out_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgRewardsOptOut( + sender="sender", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_rewards_opt_out instead" + + def test_msg_admin_update_binary_options_market_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgAdminUpdateBinaryOptionsMarket( + sender="sender", + market_id=market.id, + status="Paused", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_admin_update_binary_options_market instead" + ) diff --git a/tests/test_orderhash.py b/tests/test_orderhash.py index c57b6305..c2940d8d 100644 --- a/tests/test_orderhash.py +++ b/tests/test_orderhash.py @@ -1,3 +1,5 @@ +from decimal import Decimal + from pyinjective import PrivateKey from pyinjective.composer import Composer from pyinjective.core.network import Network @@ -22,23 +24,21 @@ def test_spot_order_hash(self, requests_mock): fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" spot_orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.524, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("0.524"), + quantity=Decimal("0.01"), + order_type="BUY", ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=27.92, - quantity=0.01, - is_buy=False, - is_po=False, + price=Decimal("27.92"), + quantity=Decimal("0.01"), + order_type="SELL", ), ]