diff --git a/README.md b/README.md index fdb3ae19..fa59c16e 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,11 @@ make tests **0.7.1.1** * Fixed Testnet network URLs +**0.7.1.1** +* Fixed Testnet network URLs + **0.7.1** -* Include implementation of the MessageBroadcaster, to simplify the transaction creation and broadcasting process. +* Include implementation of the TransactionBroadcaster, to simplify the transaction creation and broadcasting process. **0.7.0.6** * ADD SEI/USDT in metadata diff --git a/examples/SendToInjective.py b/examples/SendToInjective.py index 7a27841b..5d0d1072 100644 --- a/examples/SendToInjective.py +++ b/examples/SendToInjective.py @@ -4,7 +4,7 @@ import asyncio import logging -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.sendtocosmos import Peggo import importlib.resources as pkg_resources diff --git a/examples/chain_client/0_LocalOrderHash.py b/examples/chain_client/0_LocalOrderHash.py index 6c037209..7ce7de68 100644 --- a/examples/chain_client/0_LocalOrderHash.py +++ b/examples/chain_client/0_LocalOrderHash.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey from pyinjective.orderhash import OrderHashManager diff --git a/examples/chain_client/13_MsgIncreasePositionMargin.py b/examples/chain_client/13_MsgIncreasePositionMargin.py index 46630a99..2aa66a13 100644 --- a/examples/chain_client/13_MsgIncreasePositionMargin.py +++ b/examples/chain_client/13_MsgIncreasePositionMargin.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/15_MsgWithdraw.py b/examples/chain_client/15_MsgWithdraw.py index 5694ae46..51baf733 100644 --- a/examples/chain_client/15_MsgWithdraw.py +++ b/examples/chain_client/15_MsgWithdraw.py @@ -16,7 +16,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/16_MsgSubaccountTransfer.py b/examples/chain_client/16_MsgSubaccountTransfer.py index 3af6e7a7..80cb0ee5 100644 --- a/examples/chain_client/16_MsgSubaccountTransfer.py +++ b/examples/chain_client/16_MsgSubaccountTransfer.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/17_MsgBatchUpdateOrders.py b/examples/chain_client/17_MsgBatchUpdateOrders.py index bcfff042..4ce2cc56 100644 --- a/examples/chain_client/17_MsgBatchUpdateOrders.py +++ b/examples/chain_client/17_MsgBatchUpdateOrders.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/18_MsgBid.py b/examples/chain_client/18_MsgBid.py index e48ef1fa..eba03940 100644 --- a/examples/chain_client/18_MsgBid.py +++ b/examples/chain_client/18_MsgBid.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey async def main() -> None: diff --git a/examples/chain_client/19_MsgGrant.py b/examples/chain_client/19_MsgGrant.py index 2b0bbb7b..1d58a24b 100644 --- a/examples/chain_client/19_MsgGrant.py +++ b/examples/chain_client/19_MsgGrant.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/1_MsgSend.py b/examples/chain_client/1_MsgSend.py index 0a37afc1..ad24b941 100644 --- a/examples/chain_client/1_MsgSend.py +++ b/examples/chain_client/1_MsgSend.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey @@ -11,8 +11,7 @@ async def main() -> None: network = Network.testnet() # initialize grpc client - # set custom cookie location (optional) - defaults to current dir - client = AsyncClient(network, insecure=False, chain_cookie_location="/tmp/.chain_cookie") + client = AsyncClient(network, insecure=False) composer = await client.composer() await client.sync_timeout_height() diff --git a/examples/chain_client/20_MsgExec.py b/examples/chain_client/20_MsgExec.py index 231a939f..12f4526c 100644 --- a/examples/chain_client/20_MsgExec.py +++ b/examples/chain_client/20_MsgExec.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey, Address diff --git a/examples/chain_client/21_MsgRevoke.py b/examples/chain_client/21_MsgRevoke.py index e6d35bd2..db39f714 100644 --- a/examples/chain_client/21_MsgRevoke.py +++ b/examples/chain_client/21_MsgRevoke.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/22_MsgSendToEth.py b/examples/chain_client/22_MsgSendToEth.py index 3b9abfc8..afaf3030 100644 --- a/examples/chain_client/22_MsgSendToEth.py +++ b/examples/chain_client/22_MsgSendToEth.py @@ -3,7 +3,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey async def main() -> None: diff --git a/examples/chain_client/23_MsgRelayPriceFeedPrice.py b/examples/chain_client/23_MsgRelayPriceFeedPrice.py index 1f9bfc53..e17f05a2 100644 --- a/examples/chain_client/23_MsgRelayPriceFeedPrice.py +++ b/examples/chain_client/23_MsgRelayPriceFeedPrice.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/24_MsgRewardsOptOut.py b/examples/chain_client/24_MsgRewardsOptOut.py index 34c48bc7..da4fc0fc 100644 --- a/examples/chain_client/24_MsgRewardsOptOut.py +++ b/examples/chain_client/24_MsgRewardsOptOut.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/25_MsgDelegate.py b/examples/chain_client/25_MsgDelegate.py index d040dfd2..f2f25db6 100644 --- a/examples/chain_client/25_MsgDelegate.py +++ b/examples/chain_client/25_MsgDelegate.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/26_MsgWithdrawDelegatorReward.py b/examples/chain_client/26_MsgWithdrawDelegatorReward.py index c133f0ec..99d87b62 100644 --- a/examples/chain_client/26_MsgWithdrawDelegatorReward.py +++ b/examples/chain_client/26_MsgWithdrawDelegatorReward.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/27_Grants.py b/examples/chain_client/27_Grants.py index 7f16ecac..2ff81236 100644 --- a/examples/chain_client/27_Grants.py +++ b/examples/chain_client/27_Grants.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/chain_client/28_BankBalances.py b/examples/chain_client/28_BankBalances.py index 6a185ccc..84424426 100644 --- a/examples/chain_client/28_BankBalances.py +++ b/examples/chain_client/28_BankBalances.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/chain_client/29_BankBalance.py b/examples/chain_client/29_BankBalance.py index aab01086..1f38a02d 100644 --- a/examples/chain_client/29_BankBalance.py +++ b/examples/chain_client/29_BankBalance.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/chain_client/2_MsgDeposit.py b/examples/chain_client/2_MsgDeposit.py index a1684ddc..709c0bf2 100644 --- a/examples/chain_client/2_MsgDeposit.py +++ b/examples/chain_client/2_MsgDeposit.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/30_ExternalTransfer.py b/examples/chain_client/30_ExternalTransfer.py index 1fcef982..ab2b9034 100644 --- a/examples/chain_client/30_ExternalTransfer.py +++ b/examples/chain_client/30_ExternalTransfer.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py index 0d33b93d..dfa03aa3 100644 --- a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py +++ b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py @@ -2,7 +2,8 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network, Denom +from pyinjective.constant import Denom +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey async def main() -> None: diff --git a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py index 12b808c4..62030441 100644 --- a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py +++ b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py index 7a4d1197..557f1dd9 100644 --- a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py +++ b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py index 5037c899..78e7e88e 100644 --- a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py +++ b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py index e20e54b9..99510b6b 100644 --- a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py +++ b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/36_MsgRelayProviderPrices.py b/examples/chain_client/36_MsgRelayProviderPrices.py index bd88d650..41cabe90 100644 --- a/examples/chain_client/36_MsgRelayProviderPrices.py +++ b/examples/chain_client/36_MsgRelayProviderPrices.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/37_GetTx.py b/examples/chain_client/37_GetTx.py index 2e2487bc..d2eb72fa 100644 --- a/examples/chain_client/37_GetTx.py +++ b/examples/chain_client/37_GetTx.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/chain_client/38_StreamEventOrderFail.py b/examples/chain_client/38_StreamEventOrderFail.py index 1b3f760f..e453fd12 100644 --- a/examples/chain_client/38_StreamEventOrderFail.py +++ b/examples/chain_client/38_StreamEventOrderFail.py @@ -4,7 +4,8 @@ import websockets import base64 -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.mainnet() diff --git a/examples/chain_client/39_Account.py b/examples/chain_client/39_Account.py index 50d30c76..b30232ec 100644 --- a/examples/chain_client/39_Account.py +++ b/examples/chain_client/39_Account.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/chain_client/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/3_MsgCreateSpotLimitOrder.py index 5501b01b..daba1a39 100644 --- a/examples/chain_client/3_MsgCreateSpotLimitOrder.py +++ b/examples/chain_client/3_MsgCreateSpotLimitOrder.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/40_MsgExecuteContract.py b/examples/chain_client/40_MsgExecuteContract.py index d3ab1dda..949caa1d 100644 --- a/examples/chain_client/40_MsgExecuteContract.py +++ b/examples/chain_client/40_MsgExecuteContract.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/41_MsgCreateInsuranceFund.py b/examples/chain_client/41_MsgCreateInsuranceFund.py index 1a511f05..3fb0c5cc 100644 --- a/examples/chain_client/41_MsgCreateInsuranceFund.py +++ b/examples/chain_client/41_MsgCreateInsuranceFund.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey async def main() -> None: diff --git a/examples/chain_client/42_MsgUnderwrite.py b/examples/chain_client/42_MsgUnderwrite.py index d7d04fb3..79cfe5d7 100644 --- a/examples/chain_client/42_MsgUnderwrite.py +++ b/examples/chain_client/42_MsgUnderwrite.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey async def main() -> None: diff --git a/examples/chain_client/43_MsgRequestRedemption.py b/examples/chain_client/43_MsgRequestRedemption.py index 640a42d2..8d434368 100644 --- a/examples/chain_client/43_MsgRequestRedemption.py +++ b/examples/chain_client/43_MsgRequestRedemption.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey async def main() -> None: diff --git a/examples/chain_client/44_MessageBroadcaster.py b/examples/chain_client/44_MessageBroadcaster.py index b144c0cc..10d157fc 100644 --- a/examples/chain_client/44_MessageBroadcaster.py +++ b/examples/chain_client/44_MessageBroadcaster.py @@ -2,7 +2,7 @@ from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py b/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py index f0b4c7e8..81417a1e 100644 --- a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py +++ b/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py @@ -3,7 +3,7 @@ from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.async_client import AsyncClient from pyinjective.core.broadcaster import MsgBroadcasterWithPk -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey, Address diff --git a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py b/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py new file mode 100644 index 00000000..4e062d63 --- /dev/null +++ b/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py @@ -0,0 +1,64 @@ +import asyncio + +from pyinjective.composer import Composer as ProtoMsgComposer +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + # 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, + private_key=private_key_in_hexa, + use_secure_connection=True + ) + + priv_key = PrivateKey.from_hex(private_key_in_hexa) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + subaccount_id = address.get_subaccount_id(index=0) + + # prepare trade info + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + + spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + + spot_orders_to_create = [ + composer.SpotOrder( + market_id=spot_market_id_create, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=3, + quantity=55, + is_buy=True, + is_po=False + ), + composer.SpotOrder( + market_id=spot_market_id_create, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=300, + quantity=55, + is_buy=False, + is_po=False + ), + ] + + # prepare tx msg + msg = composer.MsgBatchUpdateOrders( + sender=address.to_acc_bech32(), + spot_orders_to_create=spot_orders_to_create, + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(result) + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py b/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py new file mode 100644 index 00000000..371f852d --- /dev/null +++ b/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py @@ -0,0 +1,54 @@ +import asyncio + +from pyinjective.composer import Composer as ProtoMsgComposer +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey, Address + + +async def main() -> None: + # 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_in_hexa = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" + priv_key = PrivateKey.from_hex(private_key_in_hexa) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + + message_broadcaster = MsgBroadcasterWithPk.new_for_grantee_account_without_simulation( + network=network, + grantee_private_key=private_key_in_hexa, + use_secure_connection=True + ) + + # 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, + market_id=market_id, + subaccount_id=granter_subaccount_id, + fee_recipient=address.to_acc_bech32(), + price=7.523, + quantity=0.01, + is_buy=True, + is_po=False + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([msg]) + print("---Transaction Response---") + print(result) + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/4_MsgCreateSpotMarketOrder.py index 0f234d0b..827e653d 100644 --- a/examples/chain_client/4_MsgCreateSpotMarketOrder.py +++ b/examples/chain_client/4_MsgCreateSpotMarketOrder.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/5_MsgCancelSpotOrder.py b/examples/chain_client/5_MsgCancelSpotOrder.py index ced2467f..602beb7a 100644 --- a/examples/chain_client/5_MsgCancelSpotOrder.py +++ b/examples/chain_client/5_MsgCancelSpotOrder.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py index b507ac71..dc175e20 100644 --- a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py index d7b0b574..88a18eb8 100644 --- a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py +++ b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/chain_client/8_MsgCancelDerivativeOrder.py b/examples/chain_client/8_MsgCancelDerivativeOrder.py index 2f668e5c..3784bdc6 100644 --- a/examples/chain_client/8_MsgCancelDerivativeOrder.py +++ b/examples/chain_client/8_MsgCancelDerivativeOrder.py @@ -2,7 +2,7 @@ from pyinjective.async_client import AsyncClient from pyinjective.transaction import Transaction -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.wallet import PrivateKey diff --git a/examples/exchange_client/accounts_rpc/1_StreamSubaccountBalance.py b/examples/exchange_client/accounts_rpc/1_StreamSubaccountBalance.py index 53d85f90..bc0017ba 100644 --- a/examples/exchange_client/accounts_rpc/1_StreamSubaccountBalance.py +++ b/examples/exchange_client/accounts_rpc/1_StreamSubaccountBalance.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/accounts_rpc/2_SubaccountBalance.py b/examples/exchange_client/accounts_rpc/2_SubaccountBalance.py index 61ef0396..eeabafd1 100644 --- a/examples/exchange_client/accounts_rpc/2_SubaccountBalance.py +++ b/examples/exchange_client/accounts_rpc/2_SubaccountBalance.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/accounts_rpc/3_SubaccountsList.py b/examples/exchange_client/accounts_rpc/3_SubaccountsList.py index d037106c..54abf051 100644 --- a/examples/exchange_client/accounts_rpc/3_SubaccountsList.py +++ b/examples/exchange_client/accounts_rpc/3_SubaccountsList.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/accounts_rpc/4_SubaccountBalancesList.py b/examples/exchange_client/accounts_rpc/4_SubaccountBalancesList.py index c5c8b9de..49320cfa 100644 --- a/examples/exchange_client/accounts_rpc/4_SubaccountBalancesList.py +++ b/examples/exchange_client/accounts_rpc/4_SubaccountBalancesList.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/accounts_rpc/5_SubaccountHistory.py b/examples/exchange_client/accounts_rpc/5_SubaccountHistory.py index 66d9875b..93e75d89 100644 --- a/examples/exchange_client/accounts_rpc/5_SubaccountHistory.py +++ b/examples/exchange_client/accounts_rpc/5_SubaccountHistory.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/accounts_rpc/6_SubaccountOrderSummary.py b/examples/exchange_client/accounts_rpc/6_SubaccountOrderSummary.py index f0bf85fd..eb49ee05 100644 --- a/examples/exchange_client/accounts_rpc/6_SubaccountOrderSummary.py +++ b/examples/exchange_client/accounts_rpc/6_SubaccountOrderSummary.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/accounts_rpc/7_OrderStates.py b/examples/exchange_client/accounts_rpc/7_OrderStates.py index c0851ed6..75747360 100644 --- a/examples/exchange_client/accounts_rpc/7_OrderStates.py +++ b/examples/exchange_client/accounts_rpc/7_OrderStates.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/accounts_rpc/8_Portfolio.py b/examples/exchange_client/accounts_rpc/8_Portfolio.py index 9fea55a5..3f6fdd48 100644 --- a/examples/exchange_client/accounts_rpc/8_Portfolio.py +++ b/examples/exchange_client/accounts_rpc/8_Portfolio.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/accounts_rpc/9_Rewards.py b/examples/exchange_client/accounts_rpc/9_Rewards.py index f99d804f..a3139ab2 100644 --- a/examples/exchange_client/accounts_rpc/9_Rewards.py +++ b/examples/exchange_client/accounts_rpc/9_Rewards.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/auctions_rpc/1_Auction.py b/examples/exchange_client/auctions_rpc/1_Auction.py index 79fd2dc8..ec6a80ad 100644 --- a/examples/exchange_client/auctions_rpc/1_Auction.py +++ b/examples/exchange_client/auctions_rpc/1_Auction.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/auctions_rpc/2_Auctions.py b/examples/exchange_client/auctions_rpc/2_Auctions.py index fca61338..0fa3b5b4 100644 --- a/examples/exchange_client/auctions_rpc/2_Auctions.py +++ b/examples/exchange_client/auctions_rpc/2_Auctions.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/auctions_rpc/3_StreamBids.py b/examples/exchange_client/auctions_rpc/3_StreamBids.py index 60b6927f..5078f981 100644 --- a/examples/exchange_client/auctions_rpc/3_StreamBids.py +++ b/examples/exchange_client/auctions_rpc/3_StreamBids.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/10_StreamHistoricalOrders.py b/examples/exchange_client/derivative_exchange_rpc/10_StreamHistoricalOrders.py index 33ef76e4..22081c71 100644 --- a/examples/exchange_client/derivative_exchange_rpc/10_StreamHistoricalOrders.py +++ b/examples/exchange_client/derivative_exchange_rpc/10_StreamHistoricalOrders.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/11_Trades.py b/examples/exchange_client/derivative_exchange_rpc/11_Trades.py index 056d2155..665e4651 100644 --- a/examples/exchange_client/derivative_exchange_rpc/11_Trades.py +++ b/examples/exchange_client/derivative_exchange_rpc/11_Trades.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/12_StreamTrades.py b/examples/exchange_client/derivative_exchange_rpc/12_StreamTrades.py index 31dabd25..c6b6c48d 100644 --- a/examples/exchange_client/derivative_exchange_rpc/12_StreamTrades.py +++ b/examples/exchange_client/derivative_exchange_rpc/12_StreamTrades.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/13_SubaccountOrdersList.py b/examples/exchange_client/derivative_exchange_rpc/13_SubaccountOrdersList.py index 587e3b0e..d899ba2f 100644 --- a/examples/exchange_client/derivative_exchange_rpc/13_SubaccountOrdersList.py +++ b/examples/exchange_client/derivative_exchange_rpc/13_SubaccountOrdersList.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/14_SubaccountTradesList.py b/examples/exchange_client/derivative_exchange_rpc/14_SubaccountTradesList.py index 0d835437..adf2cee5 100644 --- a/examples/exchange_client/derivative_exchange_rpc/14_SubaccountTradesList.py +++ b/examples/exchange_client/derivative_exchange_rpc/14_SubaccountTradesList.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/15_FundingPayments.py b/examples/exchange_client/derivative_exchange_rpc/15_FundingPayments.py index ebde0a71..0f15c537 100644 --- a/examples/exchange_client/derivative_exchange_rpc/15_FundingPayments.py +++ b/examples/exchange_client/derivative_exchange_rpc/15_FundingPayments.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/17_FundingRates.py b/examples/exchange_client/derivative_exchange_rpc/17_FundingRates.py index 089b89b6..04122a7c 100644 --- a/examples/exchange_client/derivative_exchange_rpc/17_FundingRates.py +++ b/examples/exchange_client/derivative_exchange_rpc/17_FundingRates.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/18_Orderbooks.py b/examples/exchange_client/derivative_exchange_rpc/18_Orderbooks.py index 3996c9f2..cc1c8aca 100644 --- a/examples/exchange_client/derivative_exchange_rpc/18_Orderbooks.py +++ b/examples/exchange_client/derivative_exchange_rpc/18_Orderbooks.py @@ -2,7 +2,7 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network async def main() -> None: diff --git a/examples/exchange_client/derivative_exchange_rpc/19_Binary_Options_Markets.py b/examples/exchange_client/derivative_exchange_rpc/19_Binary_Options_Markets.py index f7e9b111..1fef009f 100644 --- a/examples/exchange_client/derivative_exchange_rpc/19_Binary_Options_Markets.py +++ b/examples/exchange_client/derivative_exchange_rpc/19_Binary_Options_Markets.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/derivative_exchange_rpc/1_Market.py b/examples/exchange_client/derivative_exchange_rpc/1_Market.py index 7666efe3..d2c6e80b 100644 --- a/examples/exchange_client/derivative_exchange_rpc/1_Market.py +++ b/examples/exchange_client/derivative_exchange_rpc/1_Market.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/20_Binary_Options_Market.py b/examples/exchange_client/derivative_exchange_rpc/20_Binary_Options_Market.py index 59949fee..0d1b9150 100644 --- a/examples/exchange_client/derivative_exchange_rpc/20_Binary_Options_Market.py +++ b/examples/exchange_client/derivative_exchange_rpc/20_Binary_Options_Market.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/derivative_exchange_rpc/21_Historical_Orders.py b/examples/exchange_client/derivative_exchange_rpc/21_Historical_Orders.py index 367ee214..eed98d99 100644 --- a/examples/exchange_client/derivative_exchange_rpc/21_Historical_Orders.py +++ b/examples/exchange_client/derivative_exchange_rpc/21_Historical_Orders.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/22_OrderbooksV2.py b/examples/exchange_client/derivative_exchange_rpc/22_OrderbooksV2.py index 35fe128f..8205a694 100644 --- a/examples/exchange_client/derivative_exchange_rpc/22_OrderbooksV2.py +++ b/examples/exchange_client/derivative_exchange_rpc/22_OrderbooksV2.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/2_Markets.py b/examples/exchange_client/derivative_exchange_rpc/2_Markets.py index 89242d02..9b7ec94f 100644 --- a/examples/exchange_client/derivative_exchange_rpc/2_Markets.py +++ b/examples/exchange_client/derivative_exchange_rpc/2_Markets.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/3_StreamMarket.py b/examples/exchange_client/derivative_exchange_rpc/3_StreamMarket.py index f4f09d9a..b44fa804 100644 --- a/examples/exchange_client/derivative_exchange_rpc/3_StreamMarket.py +++ b/examples/exchange_client/derivative_exchange_rpc/3_StreamMarket.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/4_Orderbook.py b/examples/exchange_client/derivative_exchange_rpc/4_Orderbook.py index 61575bc8..8d891a6c 100644 --- a/examples/exchange_client/derivative_exchange_rpc/4_Orderbook.py +++ b/examples/exchange_client/derivative_exchange_rpc/4_Orderbook.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/5_StreamOrderbooks.py b/examples/exchange_client/derivative_exchange_rpc/5_StreamOrderbooks.py index b50535ee..64304ec4 100644 --- a/examples/exchange_client/derivative_exchange_rpc/5_StreamOrderbooks.py +++ b/examples/exchange_client/derivative_exchange_rpc/5_StreamOrderbooks.py @@ -2,7 +2,7 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network async def main() -> None: diff --git a/examples/exchange_client/derivative_exchange_rpc/6_StreamOrderbookUpdate.py b/examples/exchange_client/derivative_exchange_rpc/6_StreamOrderbookUpdate.py index b1ac8804..b5f48c5a 100644 --- a/examples/exchange_client/derivative_exchange_rpc/6_StreamOrderbookUpdate.py +++ b/examples/exchange_client/derivative_exchange_rpc/6_StreamOrderbookUpdate.py @@ -3,7 +3,7 @@ from decimal import * from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network class PriceLevel: diff --git a/examples/exchange_client/derivative_exchange_rpc/7_Positions.py b/examples/exchange_client/derivative_exchange_rpc/7_Positions.py index f91ec4e8..36e871cb 100644 --- a/examples/exchange_client/derivative_exchange_rpc/7_Positions.py +++ b/examples/exchange_client/derivative_exchange_rpc/7_Positions.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/derivative_exchange_rpc/9_StreamPositions.py b/examples/exchange_client/derivative_exchange_rpc/9_StreamPositions.py index c1bad053..32586681 100644 --- a/examples/exchange_client/derivative_exchange_rpc/9_StreamPositions.py +++ b/examples/exchange_client/derivative_exchange_rpc/9_StreamPositions.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/explorer_rpc/10_GetIBCTransfers.py b/examples/exchange_client/explorer_rpc/10_GetIBCTransfers.py index 38602907..945d5313 100644 --- a/examples/exchange_client/explorer_rpc/10_GetIBCTransfers.py +++ b/examples/exchange_client/explorer_rpc/10_GetIBCTransfers.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/explorer_rpc/1_GetTxByHash.py b/examples/exchange_client/explorer_rpc/1_GetTxByHash.py index 7362d1e0..ad1be37f 100644 --- a/examples/exchange_client/explorer_rpc/1_GetTxByHash.py +++ b/examples/exchange_client/explorer_rpc/1_GetTxByHash.py @@ -3,7 +3,8 @@ from pyinjective.async_client import AsyncClient from pyinjective.composer import Composer -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/explorer_rpc/2_AccountTxs.py b/examples/exchange_client/explorer_rpc/2_AccountTxs.py index 7e5c7a3f..f0f7cca0 100644 --- a/examples/exchange_client/explorer_rpc/2_AccountTxs.py +++ b/examples/exchange_client/explorer_rpc/2_AccountTxs.py @@ -3,7 +3,8 @@ from pyinjective.async_client import AsyncClient from pyinjective.composer import Composer -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/explorer_rpc/3_Blocks.py b/examples/exchange_client/explorer_rpc/3_Blocks.py index 0b636ffd..0035c51d 100644 --- a/examples/exchange_client/explorer_rpc/3_Blocks.py +++ b/examples/exchange_client/explorer_rpc/3_Blocks.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/explorer_rpc/4_Block.py b/examples/exchange_client/explorer_rpc/4_Block.py index 91aac693..6ac9982f 100644 --- a/examples/exchange_client/explorer_rpc/4_Block.py +++ b/examples/exchange_client/explorer_rpc/4_Block.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/explorer_rpc/5_TxsRequest.py b/examples/exchange_client/explorer_rpc/5_TxsRequest.py index d8c53771..e01a7066 100644 --- a/examples/exchange_client/explorer_rpc/5_TxsRequest.py +++ b/examples/exchange_client/explorer_rpc/5_TxsRequest.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/explorer_rpc/6_StreamTxs.py b/examples/exchange_client/explorer_rpc/6_StreamTxs.py index d146ea81..52cde6d3 100644 --- a/examples/exchange_client/explorer_rpc/6_StreamTxs.py +++ b/examples/exchange_client/explorer_rpc/6_StreamTxs.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/explorer_rpc/7_StreamBlocks.py b/examples/exchange_client/explorer_rpc/7_StreamBlocks.py index da755cdb..a460ee14 100644 --- a/examples/exchange_client/explorer_rpc/7_StreamBlocks.py +++ b/examples/exchange_client/explorer_rpc/7_StreamBlocks.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/explorer_rpc/8_GetPeggyDeposits.py b/examples/exchange_client/explorer_rpc/8_GetPeggyDeposits.py index b2ecb90a..32a8f01a 100644 --- a/examples/exchange_client/explorer_rpc/8_GetPeggyDeposits.py +++ b/examples/exchange_client/explorer_rpc/8_GetPeggyDeposits.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/explorer_rpc/9_GetPeggyWithdrawals.py b/examples/exchange_client/explorer_rpc/9_GetPeggyWithdrawals.py index fc12d7a6..889b46df 100644 --- a/examples/exchange_client/explorer_rpc/9_GetPeggyWithdrawals.py +++ b/examples/exchange_client/explorer_rpc/9_GetPeggyWithdrawals.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/insurance_rpc/1_InsuranceFunds.py b/examples/exchange_client/insurance_rpc/1_InsuranceFunds.py index 7dd3a207..6e0885d1 100644 --- a/examples/exchange_client/insurance_rpc/1_InsuranceFunds.py +++ b/examples/exchange_client/insurance_rpc/1_InsuranceFunds.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/insurance_rpc/2_Redemptions.py b/examples/exchange_client/insurance_rpc/2_Redemptions.py index de0582e7..66e94ad9 100644 --- a/examples/exchange_client/insurance_rpc/2_Redemptions.py +++ b/examples/exchange_client/insurance_rpc/2_Redemptions.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/meta_rpc/1_Ping.py b/examples/exchange_client/meta_rpc/1_Ping.py index 0745dcbc..ce7bd3e3 100644 --- a/examples/exchange_client/meta_rpc/1_Ping.py +++ b/examples/exchange_client/meta_rpc/1_Ping.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/meta_rpc/2_Version.py b/examples/exchange_client/meta_rpc/2_Version.py index 3ed2581d..1cd63d81 100644 --- a/examples/exchange_client/meta_rpc/2_Version.py +++ b/examples/exchange_client/meta_rpc/2_Version.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/meta_rpc/3_Info.py b/examples/exchange_client/meta_rpc/3_Info.py index c6b5ba32..bd925f20 100644 --- a/examples/exchange_client/meta_rpc/3_Info.py +++ b/examples/exchange_client/meta_rpc/3_Info.py @@ -3,7 +3,8 @@ import time from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/meta_rpc/4_StreamKeepAlive.py b/examples/exchange_client/meta_rpc/4_StreamKeepAlive.py index e73ef56b..53092a05 100644 --- a/examples/exchange_client/meta_rpc/4_StreamKeepAlive.py +++ b/examples/exchange_client/meta_rpc/4_StreamKeepAlive.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/oracle_rpc/1_StreamPrices.py b/examples/exchange_client/oracle_rpc/1_StreamPrices.py index c4233229..3707aa72 100644 --- a/examples/exchange_client/oracle_rpc/1_StreamPrices.py +++ b/examples/exchange_client/oracle_rpc/1_StreamPrices.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/oracle_rpc/2_Price.py b/examples/exchange_client/oracle_rpc/2_Price.py index eb3abdd2..cf92aa1e 100644 --- a/examples/exchange_client/oracle_rpc/2_Price.py +++ b/examples/exchange_client/oracle_rpc/2_Price.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/oracle_rpc/3_OracleList.py b/examples/exchange_client/oracle_rpc/3_OracleList.py index 0eb58036..2ff2152c 100644 --- a/examples/exchange_client/oracle_rpc/3_OracleList.py +++ b/examples/exchange_client/oracle_rpc/3_OracleList.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/portfolio_rpc/1_AccountPortfolio.py b/examples/exchange_client/portfolio_rpc/1_AccountPortfolio.py index 4ab4def8..83b46d57 100644 --- a/examples/exchange_client/portfolio_rpc/1_AccountPortfolio.py +++ b/examples/exchange_client/portfolio_rpc/1_AccountPortfolio.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/portfolio_rpc/2_StreamAccountPortfolio.py b/examples/exchange_client/portfolio_rpc/2_StreamAccountPortfolio.py index 9c37cb42..bc587bb9 100644 --- a/examples/exchange_client/portfolio_rpc/2_StreamAccountPortfolio.py +++ b/examples/exchange_client/portfolio_rpc/2_StreamAccountPortfolio.py @@ -2,7 +2,7 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network async def main() -> None: diff --git a/examples/exchange_client/spot_exchange_rpc/10_StreamTrades.py b/examples/exchange_client/spot_exchange_rpc/10_StreamTrades.py index 392be977..d906378c 100644 --- a/examples/exchange_client/spot_exchange_rpc/10_StreamTrades.py +++ b/examples/exchange_client/spot_exchange_rpc/10_StreamTrades.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/spot_exchange_rpc/11_SubaccountOrdersList.py b/examples/exchange_client/spot_exchange_rpc/11_SubaccountOrdersList.py index 178934c5..a7ab90ef 100644 --- a/examples/exchange_client/spot_exchange_rpc/11_SubaccountOrdersList.py +++ b/examples/exchange_client/spot_exchange_rpc/11_SubaccountOrdersList.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/spot_exchange_rpc/12_SubaccountTradesList.py b/examples/exchange_client/spot_exchange_rpc/12_SubaccountTradesList.py index f67816d8..090b1fc3 100644 --- a/examples/exchange_client/spot_exchange_rpc/12_SubaccountTradesList.py +++ b/examples/exchange_client/spot_exchange_rpc/12_SubaccountTradesList.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/spot_exchange_rpc/13_StreamOrderbooks.py b/examples/exchange_client/spot_exchange_rpc/13_StreamOrderbooks.py index 5638b0d3..7171595b 100644 --- a/examples/exchange_client/spot_exchange_rpc/13_StreamOrderbooks.py +++ b/examples/exchange_client/spot_exchange_rpc/13_StreamOrderbooks.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/spot_exchange_rpc/14_Orderbooks.py b/examples/exchange_client/spot_exchange_rpc/14_Orderbooks.py index 59d23047..b8b0840f 100644 --- a/examples/exchange_client/spot_exchange_rpc/14_Orderbooks.py +++ b/examples/exchange_client/spot_exchange_rpc/14_Orderbooks.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/spot_exchange_rpc/15_HistoricalOrders.py b/examples/exchange_client/spot_exchange_rpc/15_HistoricalOrders.py index 1e3266c9..d116a8a7 100644 --- a/examples/exchange_client/spot_exchange_rpc/15_HistoricalOrders.py +++ b/examples/exchange_client/spot_exchange_rpc/15_HistoricalOrders.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/spot_exchange_rpc/1_Market.py b/examples/exchange_client/spot_exchange_rpc/1_Market.py index abc3b47a..e1c99b6e 100644 --- a/examples/exchange_client/spot_exchange_rpc/1_Market.py +++ b/examples/exchange_client/spot_exchange_rpc/1_Market.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/spot_exchange_rpc/2_Markets.py b/examples/exchange_client/spot_exchange_rpc/2_Markets.py index 59f0590b..ff7e3211 100644 --- a/examples/exchange_client/spot_exchange_rpc/2_Markets.py +++ b/examples/exchange_client/spot_exchange_rpc/2_Markets.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/spot_exchange_rpc/3_StreamMarkets.py b/examples/exchange_client/spot_exchange_rpc/3_StreamMarkets.py index 90b4a1a2..d697eeea 100644 --- a/examples/exchange_client/spot_exchange_rpc/3_StreamMarkets.py +++ b/examples/exchange_client/spot_exchange_rpc/3_StreamMarkets.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: # select network: local, testnet, mainnet diff --git a/examples/exchange_client/spot_exchange_rpc/4_Orderbook.py b/examples/exchange_client/spot_exchange_rpc/4_Orderbook.py index 19b58933..b1a107e2 100644 --- a/examples/exchange_client/spot_exchange_rpc/4_Orderbook.py +++ b/examples/exchange_client/spot_exchange_rpc/4_Orderbook.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/spot_exchange_rpc/6_Trades.py b/examples/exchange_client/spot_exchange_rpc/6_Trades.py index 46cf0ee8..aab46ba2 100644 --- a/examples/exchange_client/spot_exchange_rpc/6_Trades.py +++ b/examples/exchange_client/spot_exchange_rpc/6_Trades.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/examples/exchange_client/spot_exchange_rpc/7_StreamOrderbookSnapshot.py b/examples/exchange_client/spot_exchange_rpc/7_StreamOrderbookSnapshot.py index 5514502e..9094d4ba 100644 --- a/examples/exchange_client/spot_exchange_rpc/7_StreamOrderbookSnapshot.py +++ b/examples/exchange_client/spot_exchange_rpc/7_StreamOrderbookSnapshot.py @@ -2,7 +2,7 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network async def main() -> None: diff --git a/examples/exchange_client/spot_exchange_rpc/8_StreamOrderbookUpdate.py b/examples/exchange_client/spot_exchange_rpc/8_StreamOrderbookUpdate.py index b39bf981..ea0a0a95 100644 --- a/examples/exchange_client/spot_exchange_rpc/8_StreamOrderbookUpdate.py +++ b/examples/exchange_client/spot_exchange_rpc/8_StreamOrderbookUpdate.py @@ -3,7 +3,7 @@ from decimal import * from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network class PriceLevel: diff --git a/examples/exchange_client/spot_exchange_rpc/9_StreamHistoricalOrders.py b/examples/exchange_client/spot_exchange_rpc/9_StreamHistoricalOrders.py index 6a10b2f4..48453eed 100644 --- a/examples/exchange_client/spot_exchange_rpc/9_StreamHistoricalOrders.py +++ b/examples/exchange_client/spot_exchange_rpc/9_StreamHistoricalOrders.py @@ -2,7 +2,8 @@ import logging from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network + async def main() -> None: network = Network.testnet() diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index 8e442bd5..5f31e2e0 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -4,10 +4,8 @@ import grpc import aiocron -import datetime from decimal import Decimal -from http.cookies import SimpleCookie -from typing import Dict, List, Optional, Tuple, Union +from typing import Dict, List, Optional, Tuple, Union, Coroutine from pyinjective.composer import Composer @@ -26,17 +24,10 @@ from .proto.cosmos.auth.v1beta1 import ( query_pb2_grpc as auth_query_grpc, query_pb2 as auth_query, - auth_pb2 as auth_type, ) from .proto.cosmos.authz.v1beta1 import ( query_pb2_grpc as authz_query_grpc, query_pb2 as authz_query, - authz_pb2 as authz_type, -) -from .proto.cosmos.authz.v1beta1 import ( - query_pb2_grpc as authz_query_grpc, - query_pb2 as authz_query, - authz_pb2 as authz_type, ) from .proto.cosmos.bank.v1beta1 import ( query_pb2_grpc as bank_query_grpc, @@ -71,7 +62,7 @@ account_pb2 ) -from .constant import Network +from .core.network import Network from .utils.logger import LoggerProvider DEFAULT_TIMEOUTHEIGHT_SYNC_INTERVAL = 20 # seconds @@ -85,31 +76,14 @@ def __init__( self, network: Network, insecure: bool = False, - load_balancer: bool = True, credentials=grpc.ssl_channel_credentials(), - chain_cookie_location=".chain_cookie", ): - # use append mode to create file if not exist - self.chain_cookie_location = chain_cookie_location - cookie_file = open(chain_cookie_location, "a+") - cookie_file.close() - self.addr = "" self.number = 0 self.sequence = 0 - self.cookie_type = None - self.expiration_format = None - self.load_balancer = load_balancer self.network = network - self.cookie_type = "GCLB" - self.expiration_format = "{}" - - if self.network.string() == "testnet": - self.load_balancer = False - self.cookie_type = "grpc-cookie" - self.expiration_format = "20{}" # chain stubs self.chain_channel = ( @@ -126,14 +100,6 @@ def __init__( self.stubBank = bank_query_grpc.QueryStub(self.chain_channel) self.stubTx = tx_service_grpc.ServiceStub(self.chain_channel) - # attempt to load from disk - cookie_file = open(chain_cookie_location, "r+") - self.chain_cookie = cookie_file.read() - cookie_file.close() - LoggerProvider().logger_for_class(logging_class=self.__class__).info( - f"chain session cookie loaded from disk: {self.chain_cookie}" - ) - self.exchange_cookie = "" self.timeout_height = 1 @@ -249,91 +215,6 @@ async def sync_timeout_height(self): ) self.timeout_height = 0 - # cookie helper methods - async def fetch_cookie(self, type): - metadata = None - if type == "chain": - req = tendermint_query.GetLatestBlockRequest() - metadata = await self.stubCosmosTendermint.GetLatestBlock( - req - ).initial_metadata() - time.sleep(DEFAULT_BLOCK_TIME) - if type == "exchange": - req = exchange_meta_rpc_pb.VersionRequest() - metadata = await self.stubMeta.Version(req).initial_metadata() - return metadata - - async def renew_cookie(self, existing_cookie, type): - metadata = None - # format cookie date into RFC1123 standard - cookie = SimpleCookie() - cookie.load(existing_cookie) - - expires_at = cookie.get(f"{self.cookie_type}").get("expires") - expires_at = expires_at.replace("-", " ") - yyyy = f"{self.expiration_format}".format(expires_at[12:14]) - expires_at = expires_at[:12] + yyyy + expires_at[14:] - - # parse expire field to unix timestamp - expire_timestamp = datetime.datetime.strptime( - expires_at, "%a, %d %b %Y %H:%M:%S GMT" - ).timestamp() - - # renew session if timestamp diff < offset - timestamp_diff = expire_timestamp - int(time.time()) - if timestamp_diff < DEFAULT_SESSION_RENEWAL_OFFSET: - metadata = await self.fetch_cookie(type) - else: - metadata = (("cookie", existing_cookie),) - return metadata - - async def load_cookie(self, type): - metadata = None - if self.insecure: - return metadata - - if type == "chain": - if self.chain_cookie != "": - metadata = await self.renew_cookie(self.chain_cookie, type) - self.set_cookie(metadata, type) - else: - metadata = await self.fetch_cookie(type) - self.set_cookie(metadata, type) - - if type == "exchange": - if self.exchange_cookie != "": - metadata = await self.renew_cookie(self.exchange_cookie, type) - self.set_cookie(metadata, type) - else: - metadata = await self.fetch_cookie(type) - self.set_cookie(metadata, type) - - return metadata - - def set_cookie(self, metadata, type): - new_cookie = None - if self.insecure: - return new_cookie - - for k, v in metadata: - if k == "set-cookie": - new_cookie = v - - if new_cookie == None: - return - - if type == "chain": - # write to client instance - self.chain_cookie = new_cookie - # write to disk - cookie_file = open(self.chain_cookie_location, "w") - cookie_file.write(new_cookie) - cookie_file.close() - LoggerProvider().logger_for_class(logging_class=self.__class__).info("chain session cookie saved to disk") - - if type == "exchange": - self.exchange_cookie = new_cookie - # default client methods async def get_latest_block(self) -> tendermint_query.GetLatestBlockResponse: req = tendermint_query.GetLatestBlockRequest() @@ -341,9 +222,10 @@ async def get_latest_block(self) -> tendermint_query.GetLatestBlockResponse: async def get_account(self, address: str) -> Optional[account_pb2.EthAccount]: try: - metadata = await self.load_cookie(type="chain") + metadata = await self.network.chain_metadata( + metadata_query_provider=self._chain_cookie_metadata_requestor) account_any = (await self.stubAuth.Account( - auth_query.QueryAccountRequest.__call__(address=address), metadata=metadata + auth_query.QueryAccountRequest(address=address), metadata=metadata )).account account = account_pb2.EthAccount() if account_any.Is(account.DESCRIPTOR): @@ -379,8 +261,9 @@ async def simulate_tx( ) -> Tuple[Union[abci_type.SimulationResponse, grpc.RpcError], bool]: try: req = tx_service.SimulateRequest(tx_bytes=tx_byte) - metadata = await self.load_cookie(type="chain") - return await self.stubTx.Simulate.__call__(req, metadata=metadata), True + metadata = await self.network.chain_metadata( + metadata_query_provider=self._chain_cookie_metadata_requestor) + return await self.stubTx.Simulate(request=req, metadata=metadata), True except grpc.RpcError as err: return err, False @@ -388,24 +271,24 @@ async def send_tx_sync_mode(self, tx_byte: bytes) -> abci_type.TxResponse: req = tx_service.BroadcastTxRequest( tx_bytes=tx_byte, mode=tx_service.BroadcastMode.BROADCAST_MODE_SYNC ) - metadata = await self.load_cookie(type="chain") - result = await self.stubTx.BroadcastTx.__call__(req, metadata=metadata) + metadata = await self.network.chain_metadata(metadata_query_provider=self._chain_cookie_metadata_requestor) + result = await self.stubTx.BroadcastTx(request=req, metadata=metadata) return result.tx_response async def send_tx_async_mode(self, tx_byte: bytes) -> abci_type.TxResponse: req = tx_service.BroadcastTxRequest( tx_bytes=tx_byte, mode=tx_service.BroadcastMode.BROADCAST_MODE_ASYNC ) - metadata = await self.load_cookie(type="chain") - result = await self.stubTx.BroadcastTx.__call__(req, metadata=metadata) + metadata = await self.network.chain_metadata(metadata_query_provider=self._chain_cookie_metadata_requestor) + result = await self.stubTx.BroadcastTx(request=req, metadata=metadata) return result.tx_response async def send_tx_block_mode(self, tx_byte: bytes) -> abci_type.TxResponse: req = tx_service.BroadcastTxRequest( tx_bytes=tx_byte, mode=tx_service.BroadcastMode.BROADCAST_MODE_BLOCK ) - metadata = await self.load_cookie(type="chain") - result = await self.stubTx.BroadcastTx.__call__(req, metadata=metadata) + metadata = await self.network.chain_metadata(metadata_query_provider=self._chain_cookie_metadata_requestor) + result = await self.stubTx.BroadcastTx(request=req, metadata=metadata) return result.tx_response async def get_chain_id(self) -> str: @@ -672,8 +555,10 @@ async def stream_spot_markets(self, **kwargs): req = spot_exchange_rpc_pb.StreamMarketsRequest( market_ids=kwargs.get("market_ids") ) - metadata = await self.load_cookie(type="exchange") - return self.stubSpotExchange.StreamMarkets.__call__(req, metadata=metadata) + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor + ) + return self.stubSpotExchange.StreamMarkets(request=req, metadata=metadata) async def get_spot_orderbookV2(self, market_id: str): req = spot_exchange_rpc_pb.OrderbookV2Request(market_id=market_id) @@ -729,13 +614,17 @@ async def get_spot_trades(self, **kwargs): async def stream_spot_orderbook_snapshot(self, market_ids: List[str]): req = spot_exchange_rpc_pb.StreamOrderbookV2Request(market_ids=market_ids) - metadata = await self.load_cookie(type="exchange") - return self.stubSpotExchange.StreamOrderbookV2.__call__(req, metadata=metadata) + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor + ) + return self.stubSpotExchange.StreamOrderbookV2(request=req, metadata=metadata) async def stream_spot_orderbook_update(self, market_ids: List[str]): req = spot_exchange_rpc_pb.StreamOrderbookUpdateRequest(market_ids=market_ids) - metadata = await self.load_cookie(type="exchange") - return self.stubSpotExchange.StreamOrderbookUpdate.__call__(req, metadata=metadata) + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor + ) + return self.stubSpotExchange.StreamOrderbookUpdate(request=req, metadata=metadata) async def stream_spot_orders(self, market_id: str, **kwargs): req = spot_exchange_rpc_pb.StreamOrdersRequest( @@ -743,8 +632,10 @@ async def stream_spot_orders(self, market_id: str, **kwargs): order_side=kwargs.get("order_side"), subaccount_id=kwargs.get("subaccount_id"), ) - metadata = await self.load_cookie(type="exchange") - return self.stubSpotExchange.StreamOrders.__call__(req, metadata=metadata) + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor + ) + return self.stubSpotExchange.StreamOrders(request=req, metadata=metadata) async def stream_historical_spot_orders(self, market_id: str, **kwargs): req = spot_exchange_rpc_pb.StreamOrdersHistoryRequest( @@ -755,8 +646,10 @@ async def stream_historical_spot_orders(self, market_id: str, **kwargs): state=kwargs.get("state"), execution_types=kwargs.get("execution_types") ) - metadata = await self.load_cookie(type="exchange") - return self.stubSpotExchange.StreamOrdersHistory.__call__(req, metadata=metadata) + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor + ) + return self.stubSpotExchange.StreamOrdersHistory(request=req, metadata=metadata) async def stream_historical_derivative_orders(self, market_id: str, **kwargs): req = derivative_exchange_rpc_pb.StreamOrdersHistoryRequest( @@ -767,8 +660,10 @@ async def stream_historical_derivative_orders(self, market_id: str, **kwargs): state=kwargs.get("state"), execution_types=kwargs.get("execution_types") ) - metadata = await self.load_cookie(type="exchange") - return self.stubDerivativeExchange.StreamOrdersHistory.__call__(req, metadata=metadata) + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor + ) + return self.stubDerivativeExchange.StreamOrdersHistory(request=req, metadata=metadata) async def stream_spot_trades(self, **kwargs): req = spot_exchange_rpc_pb.StreamTradesRequest( @@ -780,8 +675,10 @@ async def stream_spot_trades(self, **kwargs): subaccount_ids=kwargs.get("subaccount_ids"), execution_types=kwargs.get("execution_types"), ) - metadata = await self.load_cookie(type="exchange") - return self.stubSpotExchange.StreamTrades.__call__(req, metadata=metadata) + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor + ) + return self.stubSpotExchange.StreamTrades(request=req, metadata=metadata) async def get_spot_subaccount_orders(self, subaccount_id: str, **kwargs): req = spot_exchange_rpc_pb.SubaccountOrdersListRequest( @@ -820,8 +717,10 @@ async def stream_derivative_markets(self, **kwargs): req = derivative_exchange_rpc_pb.StreamMarketRequest( market_ids=kwargs.get("market_ids") ) - metadata = await self.load_cookie(type="exchange") - return self.stubDerivativeExchange.StreamMarket.__call__(req, metadata=metadata) + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor + ) + return self.stubDerivativeExchange.StreamMarket(request=req, metadata=metadata) async def get_derivative_orderbook(self, market_id: str): req = derivative_exchange_rpc_pb.OrderbookV2Request(market_id=market_id) @@ -886,17 +785,17 @@ async def get_derivative_trades(self, **kwargs): async def stream_derivative_orderbook_snapshot(self, market_ids: List[str]): req = derivative_exchange_rpc_pb.StreamOrderbookV2Request(market_ids=market_ids) - metadata = await self.load_cookie(type="exchange") - return self.stubDerivativeExchange.StreamOrderbookV2.__call__( - req, metadata=metadata + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor ) + return self.stubDerivativeExchange.StreamOrderbookV2(request=req, metadata=metadata) async def stream_derivative_orderbook_update(self, market_ids: List[str]): req = derivative_exchange_rpc_pb.StreamOrderbookUpdateRequest(market_ids=market_ids) - metadata = await self.load_cookie(type="exchange") - return self.stubDerivativeExchange.StreamOrderbookUpdate.__call__( - req, metadata=metadata + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor ) + return self.stubDerivativeExchange.StreamOrderbookUpdate(request=req, metadata=metadata) async def stream_derivative_orders(self, market_id: str, **kwargs): req = derivative_exchange_rpc_pb.StreamOrdersRequest( @@ -904,8 +803,10 @@ async def stream_derivative_orders(self, market_id: str, **kwargs): order_side=kwargs.get("order_side"), subaccount_id=kwargs.get("subaccount_id"), ) - metadata = await self.load_cookie(type="exchange") - return self.stubDerivativeExchange.StreamOrders.__call__(req, metadata=metadata) + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor + ) + return self.stubDerivativeExchange.StreamOrders(request=req, metadata=metadata) async def stream_derivative_trades(self, **kwargs): req = derivative_exchange_rpc_pb.StreamTradesRequest( @@ -919,8 +820,10 @@ async def stream_derivative_trades(self, **kwargs): limit=kwargs.get("limit"), execution_types=kwargs.get("execution_types"), ) - metadata = await self.load_cookie(type="exchange") - return self.stubDerivativeExchange.StreamTrades.__call__(req, metadata=metadata) + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor + ) + return self.stubDerivativeExchange.StreamTrades(request=req, metadata=metadata) async def get_derivative_positions(self, **kwargs): req = derivative_exchange_rpc_pb.PositionsRequest( @@ -941,10 +844,10 @@ async def stream_derivative_positions(self, **kwargs): subaccount_id=kwargs.get("subaccount_id"), subaccount_ids=kwargs.get("subaccount_ids"), ) - metadata = await self.load_cookie(type="exchange") - return self.stubDerivativeExchange.StreamPositions.__call__( - req, metadata=metadata + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor ) + return self.stubDerivativeExchange.StreamPositions(request=req, metadata=metadata) async def get_derivative_liquidable_positions(self, **kwargs): req = derivative_exchange_rpc_pb.LiquidablePositionsRequest( @@ -1019,8 +922,10 @@ async def stream_account_portfolio(self, account_address: str, **kwargs): subaccount_id=kwargs.get("subaccount_id"), type=kwargs.get("type") ) - metadata = await self.load_cookie(type="exchange") - return self.stubPortfolio.StreamAccountPortfolio.__call__(req, metadata=metadata) + metadata = await self.network.exchange_metadata( + metadata_query_provider=self._exchange_cookie_metadata_requestor + ) + return self.stubPortfolio.StreamAccountPortfolio(request=req, metadata=metadata) async def composer(self): return Composer( @@ -1158,3 +1063,11 @@ def _token_representation(self, symbol: str, token_meta, denom: str, all_tokens: existing_token = token return existing_token + + def _chain_cookie_metadata_requestor(self) -> Coroutine: + request = tendermint_query.GetLatestBlockRequest() + return self.stubCosmosTendermint.GetLatestBlock(request).initial_metadata() + + def _exchange_cookie_metadata_requestor(self) -> Coroutine: + request = exchange_meta_rpc_pb.VersionRequest() + return self.stubMeta.Version(request).initial_metadata() diff --git a/pyinjective/client.py b/pyinjective/client.py index 10b82329..bb9baf7d 100644 --- a/pyinjective/client.py +++ b/pyinjective/client.py @@ -47,7 +47,7 @@ injective_auction_rpc_pb2_grpc as auction_rpc_grpc, ) -from .constant import Network +from .core.network import Network DEFAULT_TIMEOUTHEIGHT_SYNC_INTERVAL = 10 # seconds DEFAULT_TIMEOUTHEIGHT = 20 # blocks diff --git a/pyinjective/constant.py b/pyinjective/constant.py index 51320c93..49aaef3d 100644 --- a/pyinjective/constant.py +++ b/pyinjective/constant.py @@ -69,135 +69,3 @@ def load_peggy_denom(cls, network, symbol): else: config = mainnet_config return config[symbol]["peggy_denom"], int(config[symbol]["decimals"]) - - -class Network: - def __init__( - self, - lcd_endpoint: str , - tm_websocket_endpoint: str, - grpc_endpoint: str , - grpc_exchange_endpoint: str , - grpc_explorer_endpoint: str , - chain_id: str , - fee_denom: str , - env: str - ): - self.lcd_endpoint = lcd_endpoint - self.tm_websocket_endpoint = tm_websocket_endpoint - self.grpc_endpoint = grpc_endpoint - self.grpc_exchange_endpoint = grpc_exchange_endpoint - self.grpc_explorer_endpoint = grpc_explorer_endpoint - self.chain_id = chain_id - self.fee_denom = fee_denom - self.env = env - - @classmethod - def devnet(cls): - return cls( - lcd_endpoint="https://devnet.lcd.injective.dev", - tm_websocket_endpoint="wss://devnet.tm.injective.dev/websocket", - grpc_endpoint="devnet.injective.dev:9900", - grpc_exchange_endpoint="devnet.injective.dev:9910", - grpc_explorer_endpoint="devnet.injective.dev:9911", - chain_id="injective-777", - fee_denom="inj", - env="devnet" - ) - - @classmethod - def testnet(cls, node="lb"): - nodes = [ - "lb", - "sentry", - ] - if node not in nodes: - raise ValueError("Must be one of {}".format(nodes)) - - if node == "lb": - lcd_endpoint = "https://k8s.testnet.lcd.injective.network" - tm_websocket_endpoint = "wss://k8s.testnet.tm.injective.network/websocket" - grpc_endpoint = "k8s.testnet.chain.grpc.injective.network:443" - grpc_exchange_endpoint = "k8s.testnet.exchange.grpc.injective.network:443" - grpc_explorer_endpoint = "k8s.testnet.explorer.grpc.injective.network:443" - else: - lcd_endpoint = "https://testnet.lcd.injective.network" - tm_websocket_endpoint = "wss://testnet.tm.injective.network/websocket" - grpc_endpoint = "testnet.chain.grpc.injective.network" - grpc_exchange_endpoint = "testnet.exchange.grpc.injective.network" - grpc_explorer_endpoint = "testnet.explorer.grpc.injective.network" - - return cls( - lcd_endpoint=lcd_endpoint, - tm_websocket_endpoint=tm_websocket_endpoint, - grpc_endpoint=grpc_endpoint, - grpc_exchange_endpoint=grpc_exchange_endpoint, - grpc_explorer_endpoint=grpc_explorer_endpoint, - chain_id="injective-888", - fee_denom="inj", - env="testnet" - ) - - @classmethod - def mainnet(cls, node="lb"): - nodes = [ - "lb", # us, asia, prod - "sentry0", # ca, prod - "sentry1", # ca, prod - "sentry3", # us, prod - ] - if node not in nodes: - raise ValueError("Must be one of {}".format(nodes)) - - if node == "lb": - lcd_endpoint = "https://k8s.global.mainnet.lcd.injective.network:443" - tm_websocket_endpoint = "wss://k8s.global.mainnet.tm.injective.network:443/websocket" - grpc_endpoint = "k8s.global.mainnet.chain.grpc.injective.network:443" - grpc_exchange_endpoint = "k8s.global.mainnet.exchange.grpc.injective.network:443" - grpc_explorer_endpoint = "k8s.global.mainnet.explorer.grpc.injective.network:443" - else: - lcd_endpoint = f"http://{node}.injective.network:10337" - tm_websocket_endpoint = f"ws://{node}.injective.network:26657/websocket" - grpc_endpoint = f"{node}.injective.network:9900" - grpc_exchange_endpoint = f"{node}.injective.network:9910" - grpc_explorer_endpoint = f"{node}.injective.network:9911" - - return cls( - lcd_endpoint=lcd_endpoint, - tm_websocket_endpoint=tm_websocket_endpoint, - grpc_endpoint=grpc_endpoint, - grpc_exchange_endpoint=grpc_exchange_endpoint, - grpc_explorer_endpoint=grpc_explorer_endpoint, - chain_id="injective-1", - fee_denom="inj", - env="mainnet" - ) - - @classmethod - def local(cls): - return cls( - lcd_endpoint="http://localhost:10337", - tm_websocket_endpoint="ws://localhost:26657/websocket", - grpc_endpoint="localhost:9900", - grpc_exchange_endpoint="localhost:9910", - grpc_explorer_endpoint="localhost:9911", - chain_id="injective-1", - fee_denom="inj", - env="local" - ) - - @classmethod - def custom(cls, lcd_endpoint, tm_websocket_endpoint, grpc_endpoint, grpc_exchange_endpoint, grpc_explorer_endpoint, chain_id, env): - return cls( - lcd_endpoint=lcd_endpoint, - tm_websocket_endpoint=tm_websocket_endpoint, - grpc_endpoint=grpc_endpoint, - grpc_exchange_endpoint=grpc_exchange_endpoint, - grpc_explorer_endpoint=grpc_explorer_endpoint, - chain_id=chain_id, - fee_denom="inj", - env=env - ) - - def string(self): - return self.env diff --git a/pyinjective/core/broadcaster.py b/pyinjective/core/broadcaster.py index d213d8de..68a5baf1 100644 --- a/pyinjective/core/broadcaster.py +++ b/pyinjective/core/broadcaster.py @@ -8,7 +8,8 @@ from pyinjective import PrivateKey, Transaction, PublicKey from pyinjective.async_client import AsyncClient from pyinjective.composer import Composer -from pyinjective.constant import Network +from pyinjective.core.network import Network +from pyinjective.core.gas_limit_estimator import GasLimitEstimator class BroadcasterAccountConfig(ABC): @@ -86,6 +87,31 @@ def new_using_simulation( ) return instance + @classmethod + def new_without_simulation( + cls, + network: Network, + private_key: str, + use_secure_connection: bool = True, + client: Optional[AsyncClient] = None, + composer: Optional[Composer] = None, + ): + client = client or AsyncClient(network=network, insecure=not (use_secure_connection)) + composer = composer or Composer(network=client.network.string()) + account_config = StandardAccountBroadcasterConfig(private_key=private_key) + fee_calculator = MessageBasedTransactionFeeCalculator( + client=client, + composer=composer + ) + instance = cls( + network=network, + account_config=account_config, + client=client, + composer=composer, + fee_calculator=fee_calculator, + ) + return instance + @classmethod def new_for_grantee_account_using_simulation( cls, @@ -111,6 +137,31 @@ def new_for_grantee_account_using_simulation( ) return instance + @classmethod + def new_for_grantee_account_without_simulation( + cls, + network: Network, + grantee_private_key: str, + use_secure_connection: bool = True, + client: Optional[AsyncClient] = None, + composer: Optional[Composer] = None, + ): + client = client or AsyncClient(network=network, insecure=not (use_secure_connection)) + composer = composer or Composer(network=client.network.string()) + account_config = GranteeAccountBroadcasterConfig(grantee_private_key=grantee_private_key, composer=composer) + fee_calculator = MessageBasedTransactionFeeCalculator( + client=client, + composer=composer + ) + instance = cls( + network=network, + account_config=account_config, + client=client, + composer=composer, + fee_calculator=fee_calculator, + ) + return instance + async def broadcast(self, messages: List[any_pb2.Any]): await self._client.sync_timeout_height() await self._client.get_account(self._account_config.trading_injective_address) @@ -196,10 +247,16 @@ def messages_prepared_for_transaction(self, messages: List[any_pb2.Any]) -> List class SimulatedTransactionFeeCalculator(TransactionFeeCalculator): - def __init__(self, client: AsyncClient, composer: Composer, gas_price: Optional[int] = None): + def __init__( + self, + client: AsyncClient, + composer: Composer, + gas_price: Optional[int] = None, + gas_limit_adjustment_multiplier: Optional[Decimal] = None): self._client = client self._composer = composer self._gas_price = gas_price or self.DEFAULT_GAS_PRICE + self._gas_limit_adjustment_multiplier = gas_limit_adjustment_multiplier or Decimal("1.3") async def configure_gas_fee_for_transaction( self, @@ -216,7 +273,7 @@ async def configure_gas_fee_for_transaction( if not success: raise RuntimeError(f"Transaction simulation error: {sim_res}") - gas_limit = math.ceil(Decimal(str(sim_res.gas_info.gas_used)) * Decimal("1.1")) + gas_limit = math.ceil(Decimal(str(sim_res.gas_info.gas_used)) * self._gas_limit_adjustment_multiplier) fee = [ self._composer.Coin( @@ -227,3 +284,51 @@ async def configure_gas_fee_for_transaction( transaction.with_gas(gas=gas_limit) transaction.with_fee(fee=fee) + + +class MessageBasedTransactionFeeCalculator(TransactionFeeCalculator): + TRANSACTION_GAS_LIMIT = 60_000 + + def __init__( + self, + client: AsyncClient, + composer: Composer, + gas_price: Optional[int] = None): + self._client = client + self._composer = composer + self._gas_price = gas_price or self.DEFAULT_GAS_PRICE + + async def configure_gas_fee_for_transaction( + self, + transaction: Transaction, + private_key: PrivateKey, + public_key: PublicKey, + ): + messages_gas_limit = math.ceil(self._calculate_gas_limit(messages=transaction.msgs)) + transaction_gas_limit = messages_gas_limit + self.TRANSACTION_GAS_LIMIT + + fee = [ + self._composer.Coin( + amount=math.ceil(self._gas_price * transaction_gas_limit), + denom=self._client.network.fee_denom, + ) + ] + + transaction.with_gas(gas=transaction_gas_limit) + transaction.with_fee(fee=fee) + + def _message_type(self, message: any_pb2.Any) -> str: + if isinstance(message, any_pb2.Any): + message_type = message.type_url + else: + message_type = message.DESCRIPTOR.full_name + return message_type + + def _calculate_gas_limit(self, messages: List[any_pb2.Any]) -> int: + total_gas_limit = Decimal("0") + + for message in messages: + estimator = GasLimitEstimator.for_message(message=message) + total_gas_limit += estimator.gas_limit() + + return math.ceil(total_gas_limit) diff --git a/pyinjective/core/gas_limit_estimator.py b/pyinjective/core/gas_limit_estimator.py new file mode 100644 index 00000000..d21c385b --- /dev/null +++ b/pyinjective/core/gas_limit_estimator.py @@ -0,0 +1,307 @@ +from abc import ABC, abstractmethod + +from google.protobuf import any_pb2 + +from pyinjective.proto.cosmos.authz.v1beta1 import tx_pb2 as cosmos_authz_tx_pb +from pyinjective.proto.cosmos.gov.v1beta1 import tx_pb2 as gov_tx_pb +from pyinjective.proto.cosmwasm.wasm.v1 import tx_pb2 as wasm_tx_pb +from pyinjective.proto.injective.exchange.v1beta1 import tx_pb2 as injective_exchange_tx_pb + + +class GasLimitEstimator(ABC): + GENERAL_MESSAGE_GAS_LIMIT = 5_000 + BASIC_REFERENCE_GAS_LIMIT = 150_000 + + @classmethod + @abstractmethod + def applies_to(cls, message: any_pb2.Any) -> bool: + ... + + @classmethod + def for_message(cls, message: any_pb2.Any): + estimator_class = next((estimator_subclass for estimator_subclass in cls.__subclasses__() + if estimator_subclass.applies_to(message=message)), + None) + if estimator_class is None: + estimator = DefaultGasLimitEstimator() + else: + estimator = estimator_class(message=message) + + return estimator + + @abstractmethod + def gas_limit(self) -> int: + ... + + @staticmethod + def message_type(message: any_pb2.Any) -> str: + if isinstance(message, any_pb2.Any): + message_type = message.type_url + else: + message_type = message.DESCRIPTOR.full_name + return message_type + + @abstractmethod + def _message_class(self, message: any_pb2.Any): + ... + + def _parsed_message(self, message: any_pb2.Any) -> any_pb2.Any: + if isinstance(message, any_pb2.Any): + parsed_message = self._message_class(message=message).FromString(message.value) + else: + parsed_message = message + return parsed_message + + +class DefaultGasLimitEstimator(GasLimitEstimator): + DEFAULT_GAS_LIMIT = 150_000 + + @classmethod + def applies_to(cls, message: any_pb2.Any) -> bool: + return False + + def gas_limit(self) -> int: + return self.DEFAULT_GAS_LIMIT + + def _message_class(self, message: any_pb2.Any): + # This class should not try to convert messages + raise NotImplementedError + + +class BatchCreateSpotLimitOrdersGasLimitEstimator(GasLimitEstimator): + ORDER_GAS_LIMIT = 45_000 + + def __init__(self, message: any_pb2.Any): + self._message = self._parsed_message(message=message) + + @classmethod + def applies_to(cls, message: any_pb2.Any): + return cls.message_type(message=message).endswith("MsgBatchCreateSpotLimitOrders") + + def gas_limit(self) -> int: + total = 0 + total += self.GENERAL_MESSAGE_GAS_LIMIT + total += len(self._message.orders) * self.ORDER_GAS_LIMIT + + return total + + def _message_class(self, message: any_pb2.Any): + return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders + + +class BatchCancelSpotOrdersGasLimitEstimator(GasLimitEstimator): + ORDER_GAS_LIMIT = 45_000 + + def __init__(self, message: any_pb2.Any): + self._message = self._parsed_message(message=message) + + @classmethod + def applies_to(cls, message: any_pb2.Any): + return cls.message_type(message=message).endswith("MsgBatchCancelSpotOrders") + + def gas_limit(self) -> int: + total = 0 + total += self.GENERAL_MESSAGE_GAS_LIMIT + total += len(self._message.data) * self.ORDER_GAS_LIMIT + + return total + + def _message_class(self, message: any_pb2.Any): + return injective_exchange_tx_pb.MsgBatchCancelSpotOrders + + +class BatchCreateDerivativeLimitOrdersGasLimitEstimator(GasLimitEstimator): + ORDER_GAS_LIMIT = 60_000 + + def __init__(self, message: any_pb2.Any): + self._message = self._parsed_message(message=message) + + @classmethod + def applies_to(cls, message: any_pb2.Any): + return cls.message_type(message=message).endswith("MsgBatchCreateDerivativeLimitOrders") + + def gas_limit(self) -> int: + total = 0 + total += self.GENERAL_MESSAGE_GAS_LIMIT + total += len(self._message.orders) * self.ORDER_GAS_LIMIT + + return total + + def _message_class(self, message: any_pb2.Any): + return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders + + +class BatchCancelDerivativeOrdersGasLimitEstimator(GasLimitEstimator): + ORDER_GAS_LIMIT = 55_000 + + def __init__(self, message: any_pb2.Any): + self._message = self._parsed_message(message=message) + + @classmethod + def applies_to(cls, message: any_pb2.Any): + return cls.message_type(message=message).endswith("MsgBatchCancelDerivativeOrders") + + def gas_limit(self) -> int: + total = 0 + total += self.GENERAL_MESSAGE_GAS_LIMIT + total += len(self._message.data) * self.ORDER_GAS_LIMIT + + return total + + def _message_class(self, message: any_pb2.Any): + return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders + + +class BatchUpdateOrdersGasLimitEstimator(GasLimitEstimator): + SPOT_ORDER_CREATION_GAS_LIMIT = 40_000 + DERIVATIVE_ORDER_CREATION_GAS_LIMIT = 60_000 + SPOT_ORDER_CANCELATION_GAS_LIMIT = 45_000 + DERIVATIVE_ORDER_CANCELATION_GAS_LIMIT = 55_000 + CANCEL_ALL_SPOT_MARKET_GAS_LIMIT = 35_000 + CANCEL_ALL_DERIVATIVE_MARKET_GAS_LIMIT = 45_000 + MESSAGE_GAS_LIMIT = 10_000 + + AVERAGE_CANCEL_ALL_AFFECTED_ORDERS = 20 + + def __init__(self, message: any_pb2.Any): + self._message = self._parsed_message(message=message) + + @classmethod + def applies_to(cls, message: any_pb2.Any): + return cls.message_type(message=message).endswith("MsgBatchUpdateOrders") + + def gas_limit(self) -> int: + total = 0 + total += self.MESSAGE_GAS_LIMIT + total += len(self._message.spot_orders_to_create) * self.SPOT_ORDER_CREATION_GAS_LIMIT + total += len(self._message.derivative_orders_to_create) * self.DERIVATIVE_ORDER_CREATION_GAS_LIMIT + total += len(self._message.binary_options_orders_to_create) * self.DERIVATIVE_ORDER_CREATION_GAS_LIMIT + total += len(self._message.spot_orders_to_cancel) * self.SPOT_ORDER_CANCELATION_GAS_LIMIT + total += len(self._message.derivative_orders_to_cancel) * self.DERIVATIVE_ORDER_CANCELATION_GAS_LIMIT + total += len(self._message.binary_options_orders_to_cancel) * self.DERIVATIVE_ORDER_CANCELATION_GAS_LIMIT + + total += (len(self._message.spot_market_ids_to_cancel_all) + * self.CANCEL_ALL_SPOT_MARKET_GAS_LIMIT + * self.AVERAGE_CANCEL_ALL_AFFECTED_ORDERS) + total += (len(self._message.derivative_market_ids_to_cancel_all) + * self.CANCEL_ALL_DERIVATIVE_MARKET_GAS_LIMIT + * self.AVERAGE_CANCEL_ALL_AFFECTED_ORDERS) + total += (len(self._message.binary_options_market_ids_to_cancel_all) + * self.CANCEL_ALL_DERIVATIVE_MARKET_GAS_LIMIT + * self.AVERAGE_CANCEL_ALL_AFFECTED_ORDERS) + + return total + + def _message_class(self, message: any_pb2.Any): + return injective_exchange_tx_pb.MsgBatchUpdateOrders + + +class ExecGasLimitEstimator(GasLimitEstimator): + DEFAULT_GAS_LIMIT = 5_000 + + def __init__(self, message: any_pb2.Any): + self._message = self._parsed_message(message=message) + + @classmethod + def applies_to(cls, message: any_pb2.Any) -> bool: + return cls.message_type(message=message).endswith("MsgExec") + + def gas_limit(self) -> int: + total = sum([GasLimitEstimator.for_message(message=inner_message).gas_limit() + for inner_message in self._message.msgs]) + total += self.DEFAULT_GAS_LIMIT + + return total + + def _message_class(self, message: any_pb2.Any): + return cosmos_authz_tx_pb.MsgExec + + +class PrivilegedExecuteContractGasLimitEstimator(GasLimitEstimator): + + def __init__(self, message: any_pb2.Any): + self._message = self._parsed_message(message=message) + + @classmethod + def applies_to(cls, message: any_pb2.Any) -> bool: + return cls.message_type(message=message).endswith("MsgPrivilegedExecuteContract") + + def gas_limit(self) -> int: + return self.BASIC_REFERENCE_GAS_LIMIT * 6 + + def _message_class(self, message: any_pb2.Any): + return injective_exchange_tx_pb.MsgPrivilegedExecuteContract + + +class ExecuteContractGasLimitEstimator(GasLimitEstimator): + + def __init__(self, message: any_pb2.Any): + self._message = self._parsed_message(message=message) + + @classmethod + def applies_to(cls, message: any_pb2.Any) -> bool: + return cls.message_type(message=message).endswith("MsgExecuteContract") + + def gas_limit(self) -> int: + return int(self.BASIC_REFERENCE_GAS_LIMIT * 2.5) + + def _message_class(self, message: any_pb2.Any): + return wasm_tx_pb.MsgExecuteContract + + +class GeneralWasmGasLimitEstimator(GasLimitEstimator): + + def __init__(self, message: any_pb2.Any): + self._message = self._parsed_message(message=message) + + @classmethod + def applies_to(cls, message: any_pb2.Any) -> bool: + return "wasm." in cls.message_type(message=message) + + def gas_limit(self) -> int: + return int(self.BASIC_REFERENCE_GAS_LIMIT * 1.5) + + def _message_class(self, message: any_pb2.Any): + return wasm_tx_pb.MsgInstantiateContract2 + + +class GovernanceGasLimitEstimator(GasLimitEstimator): + + def __init__(self, message: any_pb2.Any): + self._message = self._parsed_message(message=message) + + @classmethod + def applies_to(cls, message: any_pb2.Any) -> bool: + message_type = cls.message_type(message=message) + return "gov." in message_type and ( + message_type.endswith("MsgDeposit") or message_type.endswith("MsgSubmitProposal") + ) + + def gas_limit(self) -> int: + return int(self.BASIC_REFERENCE_GAS_LIMIT * 15) + + def _message_class(self, message: any_pb2.Any): + if "MsgDeposit" in self.message_type(message=message): + message_class = gov_tx_pb.MsgDeposit + else: + message_class = gov_tx_pb.MsgSubmitProposal + return message_class + + +class GenericExchangeGasLimitEstimator(GasLimitEstimator): + BASIC_REFERENCE_GAS_LIMIT = 100_000 + + def __init__(self, message: any_pb2.Any): + self._message = message + + @classmethod + def applies_to(cls, message: any_pb2.Any) -> bool: + message_type = cls.message_type(message=message) + return "exchange." in message_type + + def gas_limit(self) -> int: + return self.BASIC_REFERENCE_GAS_LIMIT + + def _message_class(self, message: any_pb2.Any): + # This class applies to many different messages, but we don't need to transform from Any format + raise NotImplementedError diff --git a/pyinjective/core/network.py b/pyinjective/core/network.py new file mode 100644 index 00000000..50db599f --- /dev/null +++ b/pyinjective/core/network.py @@ -0,0 +1,394 @@ +import asyncio +import datetime +import time +from abc import ABC, abstractmethod +from http.cookies import SimpleCookie +from typing import Callable, Optional, Tuple + + +class CookieAssistant(ABC): + SESSION_RENEWAL_OFFSET = 120 + + @abstractmethod + async def chain_cookie(self, metadata_query_provider: Callable) -> str: + ... + + @abstractmethod + async def exchange_cookie(self, metadata_query_provider: Callable) -> str: + ... + + async def chain_metadata(self, metadata_query_provider: Callable) -> Tuple[Tuple[str, str]]: + cookie = await self.chain_cookie(metadata_query_provider=metadata_query_provider) + return (("cookie", cookie),) + + async def exchange_metadata(self, metadata_query_provider: Callable) -> Tuple[Tuple[str, str]]: + cookie = await self.exchange_cookie(metadata_query_provider=metadata_query_provider) + return (("cookie", cookie),) + + +class MainnetKubernetesCookieAssistant(CookieAssistant): + + def __init__(self): + self._chain_cookie: Optional[str] = None + self._exchange_cookie: Optional[str] = None + self._chain_cookie_initialization_lock = asyncio.Lock() + self._exchange_cookie_initialization_lock = asyncio.Lock() + + async def chain_cookie(self, metadata_query_provider: Callable) -> str: + if self._chain_cookie == None: + async with self._chain_cookie_initialization_lock: + if self._chain_cookie == None: + await self._fetch_chain_cookie(metadata_query_provider=metadata_query_provider) + cookie = self._chain_cookie + self._check_chain_cookie_expiration() + + return cookie + + async def exchange_cookie(self, metadata_query_provider: Callable) -> str: + if self._exchange_cookie == None: + async with self._exchange_cookie_initialization_lock: + if self._exchange_cookie == None: + await self._fetch_exchange_cookie(metadata_query_provider=metadata_query_provider) + cookie = self._exchange_cookie + self._check_exchange_cookie_expiration() + + return cookie + + async def _fetch_chain_cookie(self, metadata_query_provider: Callable): + metadata = await metadata_query_provider() + cookie_info = next((value for key, value in metadata if key == "set-cookie"), None) + + if cookie_info is None: + raise RuntimeError(f"Error fetching chain cookie ({metadata})") + + self._chain_cookie = cookie_info + + async def _fetch_exchange_cookie(self, metadata_query_provider: Callable): + metadata = await metadata_query_provider() + cookie_info = next((value for key, value in metadata if key == "set-cookie"), None) + + if cookie_info is None: + raise RuntimeError(f"Error fetching exchange cookie ({metadata})") + + self._exchange_cookie = cookie_info + + def _check_chain_cookie_expiration(self): + if self._is_cookie_expired(cookie_data=self._chain_cookie): + self._chain_cookie = None + + def _check_exchange_cookie_expiration(self): + if self._is_cookie_expired(cookie_data=self._exchange_cookie): + self._exchange_cookie = None + + def _is_cookie_expired(self, cookie_data: str) -> bool: + cookie = SimpleCookie() + cookie.load(cookie_data) + + expiration_time = datetime.datetime.strptime(cookie["GCLB"]["expires"], + "%a, %d-%b-%Y %H:%M:%S %Z").timestamp() + + timestamp_diff = expiration_time - time.time() + return timestamp_diff < self.SESSION_RENEWAL_OFFSET + + +class MainnetBareMetalCookieAssistant(CookieAssistant): + + def __init__(self): + self._chain_cookie: Optional[str] = None + self._exchange_cookie: Optional[str] = None + self._chain_cookie_initialization_lock = asyncio.Lock() + self._exchange_cookie_initialization_lock = asyncio.Lock() + + async def chain_cookie(self, metadata_query_provider: Callable) -> str: + if self._chain_cookie == None: + async with self._chain_cookie_initialization_lock: + if self._chain_cookie == None: + await self._fetch_chain_cookie(metadata_query_provider=metadata_query_provider) + cookie = self._chain_cookie + self._check_chain_cookie_expiration() + + return cookie + + async def exchange_cookie(self, metadata_query_provider: Callable) -> str: + if self._exchange_cookie == None: + async with self._exchange_cookie_initialization_lock: + if self._exchange_cookie == None: + await self._fetch_exchange_cookie(metadata_query_provider=metadata_query_provider) + cookie = self._exchange_cookie + self._check_exchange_cookie_expiration() + + return cookie + + async def _fetch_chain_cookie(self, metadata_query_provider: Callable): + metadata = await metadata_query_provider() + cookie_info = next((value for key, value in metadata if key == "set-cookie"), None) + + if cookie_info is None: + raise RuntimeError(f"Error fetching chain cookie ({metadata})") + + self._chain_cookie = cookie_info + + async def _fetch_exchange_cookie(self, metadata_query_provider: Callable): + metadata = await metadata_query_provider() + cookie_info = next((value for key, value in metadata if key == "set-cookie"), None) + + if cookie_info is None: + raise RuntimeError(f"Error fetching exchange cookie ({metadata})") + + self._exchange_cookie = cookie_info + + def _check_chain_cookie_expiration(self): + if self._is_cookie_expired(cookie_data=self._chain_cookie): + self._chain_cookie = None + + def _check_exchange_cookie_expiration(self): + if self._is_cookie_expired(cookie_data=self._exchange_cookie): + self._exchange_cookie = None + + def _is_cookie_expired(self, cookie_data: str) -> bool: + # The cookies for these nodes do not expire + return False + + +class TestnetCookieAssistant(CookieAssistant): + + def __init__(self): + self._chain_cookie: Optional[str] = None + self._exchange_cookie: Optional[str] = None + self._chain_cookie_initialization_lock = asyncio.Lock() + self._exchange_cookie_initialization_lock = asyncio.Lock() + + async def chain_cookie(self, metadata_query_provider: Callable) -> str: + if self._chain_cookie == None: + async with self._chain_cookie_initialization_lock: + if self._chain_cookie == None: + await self._fetch_chain_cookie(metadata_query_provider=metadata_query_provider) + cookie = self._chain_cookie + self._check_chain_cookie_expiration() + + return cookie + + async def exchange_cookie(self, metadata_query_provider: Callable) -> str: + if self._exchange_cookie == None: + async with self._exchange_cookie_initialization_lock: + if self._exchange_cookie == None: + await self._fetch_exchange_cookie(metadata_query_provider=metadata_query_provider) + cookie = self._exchange_cookie + self._check_exchange_cookie_expiration() + + return cookie + + async def _fetch_chain_cookie(self, metadata_query_provider: Callable): + metadata = await metadata_query_provider() + cookie_info = next((value for key, value in metadata if key == "set-cookie"), None) + + if cookie_info is None: + raise RuntimeError(f"Error fetching chain cookie ({metadata})") + + self._chain_cookie = cookie_info + + async def _fetch_exchange_cookie(self, metadata_query_provider: Callable): + metadata = await metadata_query_provider() + cookie_info = next((value for key, value in metadata if key == "set-cookie"), None) + + if cookie_info is None: + raise RuntimeError(f"Error fetching exchange cookie ({metadata})") + + self._exchange_cookie = cookie_info + + def _check_chain_cookie_expiration(self): + if self._is_cookie_expired(cookie_data=self._chain_cookie): + self._chain_cookie = None + + def _check_exchange_cookie_expiration(self): + if self._is_cookie_expired(cookie_data=self._exchange_cookie): + self._exchange_cookie = None + + def _is_cookie_expired(self, cookie_data: str) -> bool: + cookie = SimpleCookie() + cookie.load(cookie_data) + + expiration_time = datetime.datetime.strptime(cookie["grpc-cookie"]["expires"], + "%a, %d-%b-%y %H:%M:%S %Z").timestamp() + + timestamp_diff = expiration_time - time.time() + return timestamp_diff < self.SESSION_RENEWAL_OFFSET + + +class DisabledCookieAssistant(CookieAssistant): + async def chain_cookie(self, metadata_query_provider: Callable) -> str: + pass + + async def exchange_cookie(self, metadata_query_provider: Callable) -> str: + pass + + async def chain_metadata(self, metadata_query_provider: Callable) -> Tuple[Tuple[str, str]]: + return None + + async def exchange_metadata(self, metadata_query_provider: Callable) -> Tuple[Tuple[str, str]]: + return None + + +class Network: + def __init__( + self, + lcd_endpoint: str, + tm_websocket_endpoint: str, + grpc_endpoint: str, + grpc_exchange_endpoint: str, + grpc_explorer_endpoint: str, + chain_id: str, + fee_denom: str, + env: str, + cookie_assistant: CookieAssistant, + ): + self.lcd_endpoint = lcd_endpoint + self.tm_websocket_endpoint = tm_websocket_endpoint + self.grpc_endpoint = grpc_endpoint + self.grpc_exchange_endpoint = grpc_exchange_endpoint + self.grpc_explorer_endpoint = grpc_explorer_endpoint + self.chain_id = chain_id + self.fee_denom = fee_denom + self.env = env + self.cookie_assistant = cookie_assistant + + @classmethod + def devnet(cls): + return cls( + lcd_endpoint="https://devnet.lcd.injective.dev", + tm_websocket_endpoint="wss://devnet.tm.injective.dev/websocket", + grpc_endpoint="devnet.injective.dev:9900", + grpc_exchange_endpoint="devnet.injective.dev:9910", + grpc_explorer_endpoint="devnet.injective.dev:9911", + chain_id="injective-777", + fee_denom="inj", + env="devnet", + cookie_assistant=DisabledCookieAssistant(), + ) + + @classmethod + def testnet(cls, node="lb"): + nodes = [ + "lb", + "sentry", + ] + if node not in nodes: + raise ValueError("Must be one of {}".format(nodes)) + + if node == "lb": + lcd_endpoint = "https://k8s.testnet.lcd.injective.network" + tm_websocket_endpoint = "wss://k8s.testnet.tm.injective.network/websocket" + grpc_endpoint = "k8s.testnet.chain.grpc.injective.network:443" + grpc_exchange_endpoint = "k8s.testnet.exchange.grpc.injective.network:443" + grpc_explorer_endpoint = "k8s.testnet.explorer.grpc.injective.network:443" + else: + lcd_endpoint = "https://testnet.lcd.injective.network" + tm_websocket_endpoint = "wss://testnet.tm.injective.network/websocket" + grpc_endpoint = "testnet.chain.grpc.injective.network" + grpc_exchange_endpoint = "testnet.exchange.grpc.injective.network" + grpc_explorer_endpoint = "testnet.explorer.grpc.injective.network" + + return cls( + lcd_endpoint=lcd_endpoint, + tm_websocket_endpoint=tm_websocket_endpoint, + grpc_endpoint=grpc_endpoint, + grpc_exchange_endpoint=grpc_exchange_endpoint, + grpc_explorer_endpoint=grpc_explorer_endpoint, + chain_id="injective-888", + fee_denom="inj", + env="testnet", + cookie_assistant=TestnetCookieAssistant() + ) + + @classmethod + def mainnet(cls, node="lb"): + nodes = [ + "lb", # us, asia, prod + "lb_bare_metal", + "sentry0", # ca, prod + "sentry1", # ca, prod + "sentry3", # us, prod + ] + if node not in nodes: + raise ValueError("Must be one of {}".format(nodes)) + + if node == "lb": + lcd_endpoint = "https://k8s.global.mainnet.lcd.injective.network:443" + tm_websocket_endpoint = "wss://k8s.global.mainnet.tm.injective.network:443/websocket" + grpc_endpoint = "k8s.global.mainnet.chain.grpc.injective.network:443" + grpc_exchange_endpoint = "k8s.global.mainnet.exchange.grpc.injective.network:443" + grpc_explorer_endpoint = "k8s.global.mainnet.explorer.grpc.injective.network:443" + cookie_assistant = MainnetKubernetesCookieAssistant() + elif node == "lb_bare_metal": + lcd_endpoint = "https://sentry.lcd.injective.network:443" + tm_websocket_endpoint = "wss://sentry.tm.injective.network:443/websocket" + grpc_endpoint = "sentry.chain.grpc.injective.network:443" + grpc_exchange_endpoint = "sentry.exchange.grpc.injective.network:443" + grpc_explorer_endpoint = "sentry.explorer.grpc.injective.network:443" + cookie_assistant = MainnetBareMetalCookieAssistant() + else: + lcd_endpoint = f"http://{node}.injective.network:10337" + tm_websocket_endpoint = f"ws://{node}.injective.network:26657/websocket" + grpc_endpoint = f"{node}.injective.network:9900" + grpc_exchange_endpoint = f"{node}.injective.network:9910" + grpc_explorer_endpoint = f"{node}.injective.network:9911" + cookie_assistant = DisabledCookieAssistant() + + return cls( + lcd_endpoint=lcd_endpoint, + tm_websocket_endpoint=tm_websocket_endpoint, + grpc_endpoint=grpc_endpoint, + grpc_exchange_endpoint=grpc_exchange_endpoint, + grpc_explorer_endpoint=grpc_explorer_endpoint, + chain_id="injective-1", + fee_denom="inj", + env="mainnet", + cookie_assistant=cookie_assistant, + ) + + @classmethod + def local(cls): + return cls( + lcd_endpoint="http://localhost:10337", + tm_websocket_endpoint="ws://localhost:26657/websocket", + grpc_endpoint="localhost:9900", + grpc_exchange_endpoint="localhost:9910", + grpc_explorer_endpoint="localhost:9911", + chain_id="injective-1", + fee_denom="inj", + env="local", + cookie_assistant=DisabledCookieAssistant(), + ) + + @classmethod + def custom( + cls, + lcd_endpoint, + tm_websocket_endpoint, + grpc_endpoint, + grpc_exchange_endpoint, + grpc_explorer_endpoint, + chain_id, + env, + cookie_assistant: CookieAssistant, + ): + return cls( + lcd_endpoint=lcd_endpoint, + tm_websocket_endpoint=tm_websocket_endpoint, + grpc_endpoint=grpc_endpoint, + grpc_exchange_endpoint=grpc_exchange_endpoint, + grpc_explorer_endpoint=grpc_explorer_endpoint, + chain_id=chain_id, + fee_denom="inj", + env=env, + cookie_assistant=cookie_assistant + ) + + def string(self): + return self.env + + async def chain_metadata(self, metadata_query_provider: Callable) -> Tuple[Tuple[str, str]]: + return await self.cookie_assistant.chain_metadata(metadata_query_provider=metadata_query_provider) + + async def exchange_metadata(self, metadata_query_provider: Callable) -> Tuple[Tuple[str, str]]: + return await self.cookie_assistant.exchange_metadata(metadata_query_provider=metadata_query_provider) diff --git a/pyinjective/utils/fetch_metadata.py b/pyinjective/utils/fetch_metadata.py index a1a00c51..ef81cef0 100644 --- a/pyinjective/utils/fetch_metadata.py +++ b/pyinjective/utils/fetch_metadata.py @@ -1,15 +1,7 @@ import asyncio -import logging -import grpc -import pyinjective.proto.exchange.injective_spot_exchange_rpc_pb2 as spot_exchange_rpc_pb -import pyinjective.proto.exchange.injective_spot_exchange_rpc_pb2_grpc as spot_exchange_rpc_grpc -import pyinjective.proto.exchange.injective_derivative_exchange_rpc_pb2 as derivative_exchange_rpc_pb -import pyinjective.proto.exchange.injective_derivative_exchange_rpc_pb2_grpc as derivative_exchange_rpc_grpc - -from decimal import * from pyinjective.async_client import AsyncClient -from pyinjective.constant import Network +from pyinjective.core.network import Network metadata_template = """[{}] description = '{} {} {}' diff --git a/tests/core/test_gas_limit_estimator.py b/tests/core/test_gas_limit_estimator.py new file mode 100644 index 00000000..9ccbc98b --- /dev/null +++ b/tests/core/test_gas_limit_estimator.py @@ -0,0 +1,549 @@ +from decimal import Decimal + +from pyinjective.composer import Composer +from pyinjective.core.gas_limit_estimator import GasLimitEstimator +from pyinjective.core.market import BinaryOptionMarket +from pyinjective.proto.cosmos.gov.v1beta1 import tx_pb2 as gov_tx_pb +from pyinjective.proto.cosmwasm.wasm.v1 import tx_pb2 as wasm_tx_pb +from pyinjective.proto.injective.exchange.v1beta1 import tx_pb2 as injective_exchange_tx_pb + +from tests.model_fixtures.markets_fixtures import usdt_token + +class TestGasLimitEstimator: + + def test_estimation_for_message_without_applying_rule(self): + composer = Composer(network="testnet") + message = composer.MsgSend( + from_address="from_address", + to_address="to_address", + amount=1, + denom='INJ' + ) + + estimator = GasLimitEstimator.for_message(message=message) + + expected_message_gas_limit = 150_000 + + assert(expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_create_spot_limit_orders(self): + spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + composer = Composer(network="testnet") + orders = [ + composer.SpotOrder( + market_id=spot_market_id, + subaccount_id="subaccount_id", + fee_recipient="fee_recipient", + price=5, + quantity=1, + is_buy=True, + is_po=False + ), + composer.SpotOrder( + market_id=spot_market_id, + subaccount_id="subaccount_id", + fee_recipient="fee_recipient", + price=4, + quantity=1, + is_buy=True, + is_po=False + ), + ] + message = composer.MsgBatchCreateSpotLimitOrders( + sender="sender", + orders=orders + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_order_gas_limit = 45000 + expected_message_gas_limit = 5000 + + assert((expected_order_gas_limit * 2) + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_cancel_spot_orders(self): + spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + composer = Composer(network="testnet") + orders = [ + composer.OrderData( + market_id=spot_market_id, + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d" + ), + composer.OrderData( + market_id=spot_market_id, + subaccount_id="subaccount_id", + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2" + ), + composer.OrderData( + market_id=spot_market_id, + subaccount_id="subaccount_id", + order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5" + ) + ] + message = composer.MsgBatchCancelSpotOrders( + sender="sender", + data=orders + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_order_gas_limit = 45000 + expected_message_gas_limit = 5000 + + assert((expected_order_gas_limit * 3) + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_create_derivative_limit_orders(self): + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + composer = Composer(network="testnet") + orders = [ + composer.DerivativeOrder( + market_id=market_id, + subaccount_id="subaccount_id", + fee_recipient="fee_recipient", + price=3, + quantity=1, + leverage=1, + is_buy=True, + is_po=False + ), + composer.DerivativeOrder( + 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 + ), + ] + message = composer.MsgBatchCreateDerivativeLimitOrders( + sender="sender", + orders=orders + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_order_gas_limit = 60_000 + expected_message_gas_limit = 5000 + + assert((expected_order_gas_limit * 2) + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_cancel_derivative_orders(self): + spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + composer = Composer(network="testnet") + orders = [ + composer.OrderData( + market_id=spot_market_id, + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d" + ), + composer.OrderData( + market_id=spot_market_id, + subaccount_id="subaccount_id", + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2" + ), + composer.OrderData( + market_id=spot_market_id, + subaccount_id="subaccount_id", + order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5" + ) + ] + message = composer.MsgBatchCancelDerivativeOrders( + sender="sender", + data=orders + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_order_gas_limit = 55_000 + expected_message_gas_limit = 5000 + + assert((expected_order_gas_limit * 3) + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_update_orders_to_create_spot_orders(self): + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + composer = Composer(network="testnet") + orders = [ + composer.SpotOrder( + market_id=market_id, + subaccount_id="subaccount_id", + fee_recipient="fee_recipient", + price=5, + quantity=1, + is_buy=True, + is_po=False + ), + composer.SpotOrder( + market_id=market_id, + subaccount_id="subaccount_id", + fee_recipient="fee_recipient", + price=4, + quantity=1, + is_buy=True, + is_po=False + ), + ] + message = composer.MsgBatchUpdateOrders( + sender="senders", + derivative_orders_to_create=[], + spot_orders_to_create=orders, + derivative_orders_to_cancel=[], + spot_orders_to_cancel=[] + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_order_gas_limit = 40_000 + expected_message_gas_limit = 10_000 + + assert((expected_order_gas_limit * 2) + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_update_orders_to_create_derivative_orders(self): + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + composer = Composer(network="testnet") + orders = [ + composer.DerivativeOrder( + market_id=market_id, + subaccount_id="subaccount_id", + fee_recipient="fee_recipient", + price=3, + quantity=1, + leverage=1, + is_buy=True, + is_po=False + ), + composer.DerivativeOrder( + 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 + ), + ] + message = composer.MsgBatchUpdateOrders( + sender="senders", + derivative_orders_to_create=orders, + spot_orders_to_create=[], + derivative_orders_to_cancel=[], + spot_orders_to_cancel=[] + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_order_gas_limit = 60_000 + expected_message_gas_limit = 10_000 + + assert((expected_order_gas_limit * 2) + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_update_orders_to_create_binary_orders(self, usdt_token): + market_id = "0x230dcce315364ff6360097838701b14713e2f4007d704df20ed3d81d09eec957" + composer = Composer(network="testnet") + market = BinaryOptionMarket( + id=market_id, + status="active", + ticker="5fdbe0b1-1707800399-WAS", + oracle_symbol="Frontrunner", + oracle_provider="Frontrunner", + oracle_type="provider", + oracle_scale_factor=6, + expiration_timestamp=1707800399, + settlement_timestamp=1707843599, + quote_token=usdt_token, + maker_fee_rate=Decimal("0"), + taker_fee_rate=Decimal("0"), + service_provider_fee=Decimal("0.4"), + min_price_tick_size=Decimal("10000"), + min_quantity_tick_size=Decimal("1"), + ) + composer.binary_option_markets[market.id] = market + orders = [ + composer.BinaryOptionsOrder( + market_id=market_id, + subaccount_id="subaccount_id", + fee_recipient="fee_recipient", + price=3, + quantity=1, + leverage=1, + is_buy=True, + is_po=False + ), + composer.BinaryOptionsOrder( + 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 + ), + ] + message = composer.MsgBatchUpdateOrders( + sender="senders", + derivative_orders_to_create=[], + spot_orders_to_create=[], + binary_options_orders_to_create=orders, + derivative_orders_to_cancel=[], + spot_orders_to_cancel=[] + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_order_gas_limit = 60_000 + expected_message_gas_limit = 10_000 + + assert((expected_order_gas_limit * 2) + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_update_orders_to_cancel_spot_orders(self): + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + composer = Composer(network="testnet") + orders = [ + composer.OrderData( + market_id=market_id, + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d" + ), + composer.OrderData( + market_id=market_id, + subaccount_id="subaccount_id", + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2" + ), + composer.OrderData( + market_id=market_id, + subaccount_id="subaccount_id", + order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5" + ) + ] + message = composer.MsgBatchUpdateOrders( + sender="senders", + derivative_orders_to_create=[], + spot_orders_to_create=[], + derivative_orders_to_cancel=[], + spot_orders_to_cancel=orders + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_order_gas_limit = 45_000 + expected_message_gas_limit = 10_000 + + assert((expected_order_gas_limit * 3) + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_update_orders_to_cancel_derivative_orders(self): + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + composer = Composer(network="testnet") + orders = [ + composer.OrderData( + market_id=market_id, + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d" + ), + composer.OrderData( + market_id=market_id, + subaccount_id="subaccount_id", + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2" + ), + composer.OrderData( + market_id=market_id, + subaccount_id="subaccount_id", + order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5" + ) + ] + message = composer.MsgBatchUpdateOrders( + sender="senders", + derivative_orders_to_create=[], + spot_orders_to_create=[], + derivative_orders_to_cancel=orders, + spot_orders_to_cancel=[] + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_order_gas_limit = 55_000 + expected_message_gas_limit = 10_000 + + assert((expected_order_gas_limit * 3) + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_update_orders_to_cancel_binary_orders(self): + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + composer = Composer(network="testnet") + orders = [ + composer.OrderData( + market_id=market_id, + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d" + ), + composer.OrderData( + market_id=market_id, + subaccount_id="subaccount_id", + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2" + ), + composer.OrderData( + market_id=market_id, + subaccount_id="subaccount_id", + order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5" + ) + ] + message = composer.MsgBatchUpdateOrders( + sender="senders", + derivative_orders_to_create=[], + spot_orders_to_create=[], + derivative_orders_to_cancel=[], + spot_orders_to_cancel=[], + binary_options_orders_to_cancel=orders, + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_order_gas_limit = 55_000 + expected_message_gas_limit = 10_000 + + assert((expected_order_gas_limit * 3) + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_update_orders_to_cancel_all_for_spot_market(self): + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + composer = Composer(network="testnet") + + message = composer.MsgBatchUpdateOrders( + sender="senders", + subaccount_id="subaccount_id", + spot_market_ids_to_cancel_all=[market_id], + derivative_orders_to_create=[], + spot_orders_to_create=[], + derivative_orders_to_cancel=[], + spot_orders_to_cancel=[] + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_gas_limit = 35_000 * 20 + expected_message_gas_limit = 10_000 + + assert(expected_gas_limit + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_update_orders_to_cancel_all_for_derivative_market(self): + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + composer = Composer(network="testnet") + + message = composer.MsgBatchUpdateOrders( + sender="senders", + subaccount_id="subaccount_id", + derivative_market_ids_to_cancel_all=[market_id], + derivative_orders_to_create=[], + spot_orders_to_create=[], + derivative_orders_to_cancel=[], + spot_orders_to_cancel=[] + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_gas_limit = 45_000 * 20 + expected_message_gas_limit = 10_000 + + assert(expected_gas_limit + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_batch_update_orders_to_cancel_all_for_binary_options_market(self): + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + composer = Composer(network="testnet") + + message = composer.MsgBatchUpdateOrders( + sender="senders", + subaccount_id="subaccount_id", + binary_options_market_ids_to_cancel_all=[market_id], + derivative_orders_to_create=[], + spot_orders_to_create=[], + derivative_orders_to_cancel=[], + spot_orders_to_cancel=[] + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_gas_limit = 45_000 * 20 + expected_message_gas_limit = 10_000 + + assert(expected_gas_limit + expected_message_gas_limit == estimator.gas_limit()) + + def test_estimation_for_exec_message(self): + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + composer = Composer(network="testnet") + orders = [ + composer.SpotOrder( + market_id=market_id, + subaccount_id="subaccount_id", + fee_recipient="fee_recipient", + price=5, + quantity=1, + is_buy=True, + is_po=False + ), + ] + inner_message = composer.MsgBatchUpdateOrders( + sender="senders", + derivative_orders_to_create=[], + spot_orders_to_create=orders, + derivative_orders_to_cancel=[], + spot_orders_to_cancel=[] + ) + message = composer.MsgExec( + grantee="grantee", + msgs=[inner_message] + ) + + estimator = GasLimitEstimator.for_message(message=message) + + expected_order_gas_limit = 40_000 + expected_inner_message_gas_limit = 10_000 + expected_exec_message_gas_limit = 5_000 + + assert(expected_order_gas_limit + + expected_inner_message_gas_limit + + expected_exec_message_gas_limit + == estimator.gas_limit()) + + def test_estimation_for_privileged_execute_contract_message(self): + message = injective_exchange_tx_pb.MsgPrivilegedExecuteContract() + estimator = GasLimitEstimator.for_message(message=message) + + expected_gas_limit = 900_000 + + assert(expected_gas_limit == estimator.gas_limit()) + + + def test_estimation_for_execute_contract_message(self): + composer = Composer(network="testnet") + message = composer.MsgExecuteContract( + sender="", + contract="", + msg="", + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_gas_limit = 375_000 + + assert(expected_gas_limit == estimator.gas_limit()) + + def test_estimation_for_wasm_message(self): + message = wasm_tx_pb.MsgInstantiateContract2() + estimator = GasLimitEstimator.for_message(message=message) + + expected_gas_limit = 225_000 + + assert(expected_gas_limit == estimator.gas_limit()) + + def test_estimation_for_governance_message(self): + message = gov_tx_pb.MsgDeposit() + estimator = GasLimitEstimator.for_message(message=message) + + expected_gas_limit = 2_250_000 + + assert(expected_gas_limit == estimator.gas_limit()) + + def test_estimation_for_generic_exchange_message(self): + composer = Composer(network="testnet") + message = composer.MsgCreateSpotLimitOrder( + 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 + ) + estimator = GasLimitEstimator.for_message(message=message) + + expected_gas_limit = 100_000 + + assert(expected_gas_limit == estimator.gas_limit()) diff --git a/tests/core/test_message_based_transaction_fee_calculator.py b/tests/core/test_message_based_transaction_fee_calculator.py new file mode 100644 index 00000000..7525fe00 --- /dev/null +++ b/tests/core/test_message_based_transaction_fee_calculator.py @@ -0,0 +1,229 @@ +from decimal import Decimal + +import math +import pytest + +from pyinjective import Transaction +from pyinjective.async_client import AsyncClient +from pyinjective.composer import Composer +from pyinjective.core.network import Network +from pyinjective.core.broadcaster import MessageBasedTransactionFeeCalculator +from pyinjective.proto.cosmos.gov.v1beta1 import tx_pb2 as gov_tx_pb2 +from pyinjective.proto.cosmwasm.wasm.v1 import tx_pb2 as wasm_tx_pb2 +from pyinjective.proto.injective.exchange.v1beta1 import tx_pb2 + + +class TestMessageBasedTransactionFeeCalculator: + + @pytest.mark.asyncio + async def test_gas_fee_for_privileged_execute_contract_message(self): + network = Network.testnet(node="sentry") + client = AsyncClient(network=network, insecure=False) + composer = Composer(network=network.string()) + calculator = MessageBasedTransactionFeeCalculator( + client=client, + composer=composer, + gas_price=5_000_000, + ) + + message = tx_pb2.MsgPrivilegedExecuteContract() + transaction = Transaction() + transaction.with_messages(message) + + await calculator.configure_gas_fee_for_transaction(transaction=transaction, private_key=None, public_key=None) + + expected_transaction_gas_limit = 60_000 + expected_gas_limit = math.ceil(Decimal(6) * 150_000 + expected_transaction_gas_limit) + assert(expected_gas_limit == transaction.fee.gas_limit) + assert(str(expected_gas_limit * 5_000_000) == transaction.fee.amount[0].amount) + + @pytest.mark.asyncio + async def test_gas_fee_for_execute_contract_message(self): + network = Network.testnet(node="sentry") + client = AsyncClient(network=network, insecure=False) + composer = Composer(network=network.string()) + calculator = MessageBasedTransactionFeeCalculator( + client=client, + composer=composer, + gas_price=5_000_000, + ) + + message = composer.MsgExecuteContract( + sender="", + contract="", + msg="", + ) + transaction = Transaction() + transaction.with_messages(message) + + await calculator.configure_gas_fee_for_transaction(transaction=transaction, private_key=None, public_key=None) + + expected_transaction_gas_limit = 60_000 + expected_gas_limit = math.ceil(Decimal(2.5) * 150_000 + expected_transaction_gas_limit) + assert (expected_gas_limit == transaction.fee.gas_limit) + assert (str(expected_gas_limit * 5_000_000) == transaction.fee.amount[0].amount) + + @pytest.mark.asyncio + async def test_gas_fee_for_wasm_message(self): + network = Network.testnet(node="sentry") + client = AsyncClient(network=network, insecure=False) + composer = Composer(network=network.string()) + calculator = MessageBasedTransactionFeeCalculator( + client=client, + composer=composer, + gas_price=5_000_000, + ) + + message = wasm_tx_pb2.MsgInstantiateContract2() + transaction = Transaction() + transaction.with_messages(message) + + await calculator.configure_gas_fee_for_transaction(transaction=transaction, private_key=None, public_key=None) + + expected_transaction_gas_limit = 60_000 + expected_gas_limit = math.ceil(Decimal(1.5) * 150_000 + expected_transaction_gas_limit) + assert (expected_gas_limit == transaction.fee.gas_limit) + assert (str(expected_gas_limit * 5_000_000) == transaction.fee.amount[0].amount) + + @pytest.mark.asyncio + async def test_gas_fee_for_governance_message(self): + network = Network.testnet(node="sentry") + client = AsyncClient(network=network, insecure=False) + composer = Composer(network=network.string()) + calculator = MessageBasedTransactionFeeCalculator( + client=client, + composer=composer, + gas_price=5_000_000, + ) + + message = gov_tx_pb2.MsgDeposit() + transaction = Transaction() + transaction.with_messages(message) + + await calculator.configure_gas_fee_for_transaction(transaction=transaction, private_key=None, public_key=None) + + expected_transaction_gas_limit = 60_000 + expected_gas_limit = math.ceil(Decimal(15) * 150_000 + expected_transaction_gas_limit) + assert (expected_gas_limit == transaction.fee.gas_limit) + assert (str(expected_gas_limit * 5_000_000) == transaction.fee.amount[0].amount) + + @pytest.mark.asyncio + async def test_gas_fee_for_exchange_message(self): + network = Network.testnet(node="sentry") + client = AsyncClient(network=network, insecure=False) + composer = Composer(network=network.string()) + calculator = MessageBasedTransactionFeeCalculator( + client=client, + composer=composer, + gas_price=5_000_000, + ) + + message = composer.MsgCreateSpotLimitOrder( + 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 + ) + transaction = Transaction() + transaction.with_messages(message) + + await calculator.configure_gas_fee_for_transaction(transaction=transaction, private_key=None, public_key=None) + + expected_transaction_gas_limit = 60_000 + expected_gas_limit = math.ceil(Decimal(1) * 100_000 + expected_transaction_gas_limit) + assert (expected_gas_limit == transaction.fee.gas_limit) + assert (str(expected_gas_limit * 5_000_000) == transaction.fee.amount[0].amount) + + @pytest.mark.asyncio + async def test_gas_fee_for_msg_exec_message(self): + network = Network.testnet(node="sentry") + client = AsyncClient(network=network, insecure=False) + composer = Composer(network=network.string()) + calculator = MessageBasedTransactionFeeCalculator( + client=client, + composer=composer, + gas_price=5_000_000, + ) + + inner_message = composer.MsgCreateSpotLimitOrder( + 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 + ) + message = composer.MsgExec( + grantee="grantee", + msgs=[inner_message] + ) + transaction = Transaction() + transaction.with_messages(message) + + await calculator.configure_gas_fee_for_transaction(transaction=transaction, private_key=None, public_key=None) + + expected_transaction_gas_limit = 60_000 + expected_inner_message_gas_limit = Decimal(1) * 100_000 + expected_exec_message_gas_limit = 5_000 + expected_gas_limit = math.ceil( + expected_exec_message_gas_limit + expected_inner_message_gas_limit + expected_transaction_gas_limit + ) + assert (expected_gas_limit == transaction.fee.gas_limit) + assert (str(expected_gas_limit * 5_000_000) == transaction.fee.amount[0].amount) + + @pytest.mark.asyncio + async def test_gas_fee_for_two_messages_in_one_transaction(self): + network = Network.testnet(node="sentry") + client = AsyncClient(network=network, insecure=False) + composer = Composer(network=network.string()) + calculator = MessageBasedTransactionFeeCalculator( + client=client, + composer=composer, + gas_price=5_000_000, + ) + + inner_message = composer.MsgCreateSpotLimitOrder( + 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 + ) + message = composer.MsgExec( + grantee="grantee", + msgs=[inner_message] + ) + + send_message = composer.MsgSend( + from_address="address", + to_address='to_address', + amount=1, + denom='INJ' + ) + + transaction = Transaction() + transaction.with_messages(message, send_message) + + await calculator.configure_gas_fee_for_transaction(transaction=transaction, private_key=None, public_key=None) + + expected_transaction_gas_limit = 60_000 + expected_inner_message_gas_limit = Decimal(1) * 100_000 + expected_exec_message_gas_limit = 5_000 + expected_send_message_gas_limit = 150_000 + expected_gas_limit = math.ceil( + expected_exec_message_gas_limit + + expected_inner_message_gas_limit + + expected_send_message_gas_limit + + expected_transaction_gas_limit + ) + assert (expected_gas_limit == transaction.fee.gas_limit) + assert (str(expected_gas_limit * 5_000_000) == transaction.fee.amount[0].amount) diff --git a/tests/test_async_client.py b/tests/test_async_client.py index 56644e9c..8cbab554 100644 --- a/tests/test_async_client.py +++ b/tests/test_async_client.py @@ -1,7 +1,7 @@ import logging import pytest -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.async_client import AsyncClient from pyinjective.proto.exchange import ( @@ -35,24 +35,6 @@ def derivative_servicer(): class TestAsyncClient: - def test_instance_creation_logs_session_cookie_load_info(self, caplog): - caplog.set_level(logging.INFO) - - AsyncClient( - network=Network.local(), - insecure=False, - ) - - expected_log_message_prefix = "chain session cookie loaded from disk: " - found_log = next( - (record for record in caplog.record_tuples if record[2].startswith(expected_log_message_prefix)), - None, - ) - assert(found_log is not None) - assert(found_log[0] == "pyinjective.async_client.AsyncClient") - assert(found_log[1] == logging.INFO) - - @pytest.mark.asyncio async def test_sync_timeout_height_logs_exception(self, caplog): client = AsyncClient( @@ -72,25 +54,6 @@ async def test_sync_timeout_height_logs_exception(self, caplog): assert (found_log[0] == "pyinjective.async_client.AsyncClient") assert (found_log[1] == logging.DEBUG) - def test_set_cookie_logs_chain_session_cookie_saved(self, caplog): - caplog.set_level(logging.INFO) - - client = AsyncClient( - network=Network.local(), - insecure=False, - ) - - client.set_cookie(metadata=[("set-cookie", "test-value")], type="chain") - - expected_log_message_prefix = "chain session cookie saved to disk" - found_log = next( - (record for record in caplog.record_tuples if record[2].startswith(expected_log_message_prefix)), - None, - ) - assert (found_log is not None) - assert (found_log[0] == "pyinjective.async_client.AsyncClient") - assert (found_log[1] == logging.INFO) - @pytest.mark.asyncio async def test_get_account_logs_exception(self, caplog): client = AsyncClient( diff --git a/tests/test_composer.py b/tests/test_composer.py index 9c5426e5..449854ad 100644 --- a/tests/test_composer.py +++ b/tests/test_composer.py @@ -1,9 +1,9 @@ -import logging import pytest from decimal import Decimal from pyinjective.composer import Composer -from pyinjective.constant import Denom, Network +from pyinjective.core.network import Network +from pyinjective.constant import Denom from pyinjective.core.market import BinaryOptionMarket, DerivativeMarket, SpotMarket from pyinjective.proto.injective.exchange.v1beta1 import exchange_pb2 from tests.model_fixtures.markets_fixtures import ( diff --git a/tests/test_orderhash.py b/tests/test_orderhash.py index 2aff84a0..c5331e26 100644 --- a/tests/test_orderhash.py +++ b/tests/test_orderhash.py @@ -1,6 +1,6 @@ from pyinjective import PrivateKey from pyinjective.composer import Composer -from pyinjective.constant import Network +from pyinjective.core.network import Network from pyinjective.orderhash import OrderHashManager