From ae60e4df7950a75e31dd658d94c294bd3e0189ae Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 16 Jan 2024 11:52:25 -0300 Subject: [PATCH 01/44] (fix) Changed version number for dev branch --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a15c4162..a024299a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "injective-py" -version = "1.1.0" +version = "1.2.0-rc1" description = "Injective Python SDK, with Exchange API Client" authors = ["Injective Labs "] license = "Apache-2.0" From c318d0ae0bccf30ecb70e1dec2956879e9d5267a Mon Sep 17 00:00:00 2001 From: abel Date: Wed, 17 Jan 2024 10:22:45 -0300 Subject: [PATCH 02/44] (feat) Cleaned up the markets initialization logic --- pyinjective/async_client.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index ec42c2ce..e8da821b 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -9,7 +9,6 @@ import grpc from google.protobuf import json_format -from pyinjective import constant from pyinjective.client.chain.grpc.chain_grpc_auth_api import ChainGrpcAuthApi from pyinjective.client.chain.grpc.chain_grpc_authz_api import ChainGrpcAuthZApi from pyinjective.client.chain.grpc.chain_grpc_bank_api import ChainGrpcBankApi @@ -2659,22 +2658,13 @@ async def _initialize_tokens_and_markets(self): ) for market_info in valid_markets: - ticker = market_info["ticker"] - if "/" in ticker: - base_token_symbol, quote_token_symbol = ticker.split(constant.TICKER_TOKENS_SEPARATOR) - else: - base_token_symbol = market_info["baseTokenMeta"]["symbol"] - quote_token_symbol = market_info["quoteTokenMeta"]["symbol"] - base_token = self._token_representation( - symbol=base_token_symbol, token_meta=market_info["baseTokenMeta"], denom=market_info["baseDenom"], tokens_by_denom=tokens_by_denom, tokens_by_symbol=tokens_by_symbol, ) quote_token = self._token_representation( - symbol=quote_token_symbol, token_meta=market_info["quoteTokenMeta"], denom=market_info["quoteDenom"], tokens_by_denom=tokens_by_denom, @@ -2704,10 +2694,7 @@ async def _initialize_tokens_and_markets(self): ) for market_info in valid_markets: - quote_token_symbol = market_info["quoteTokenMeta"]["symbol"] - quote_token = self._token_representation( - symbol=quote_token_symbol, token_meta=market_info["quoteTokenMeta"], denom=market_info["quoteDenom"], tokens_by_denom=tokens_by_denom, @@ -2769,7 +2756,6 @@ async def _initialize_tokens_and_markets(self): def _token_representation( self, - symbol: str, token_meta: Dict[str, Any], denom: str, tokens_by_denom: Dict[str, Token], @@ -2777,14 +2763,14 @@ def _token_representation( ) -> Token: if denom not in tokens_by_denom: unique_symbol = denom - for symbol_candidate in [symbol, token_meta["symbol"], token_meta["name"]]: + for symbol_candidate in [token_meta["symbol"], token_meta["name"]]: if symbol_candidate not in tokens_by_symbol: unique_symbol = symbol_candidate break token = Token( name=token_meta["name"], - symbol=symbol, + symbol=token_meta["symbol"], denom=denom, address=token_meta["address"], decimals=token_meta["decimals"], From 352cd44099ae9520d7335e15faced02652bd32dd Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 16 Jan 2024 11:52:25 -0300 Subject: [PATCH 03/44] (fix) Changed version number for dev branch --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9ae18ae5..a1fdb3ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "injective-py" -version = "1.2.0" +version = "1.3.0-pre" description = "Injective Python SDK, with Exchange API Client" authors = ["Injective Labs "] license = "Apache-2.0" From 158b341034452fb802d621e39874c1557e9dd57a Mon Sep 17 00:00:00 2001 From: abel Date: Wed, 17 Jan 2024 10:22:45 -0300 Subject: [PATCH 04/44] (feat) Cleaned up the markets initialization logic --- pyinjective/async_client.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index ec42c2ce..e8da821b 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -9,7 +9,6 @@ import grpc from google.protobuf import json_format -from pyinjective import constant from pyinjective.client.chain.grpc.chain_grpc_auth_api import ChainGrpcAuthApi from pyinjective.client.chain.grpc.chain_grpc_authz_api import ChainGrpcAuthZApi from pyinjective.client.chain.grpc.chain_grpc_bank_api import ChainGrpcBankApi @@ -2659,22 +2658,13 @@ async def _initialize_tokens_and_markets(self): ) for market_info in valid_markets: - ticker = market_info["ticker"] - if "/" in ticker: - base_token_symbol, quote_token_symbol = ticker.split(constant.TICKER_TOKENS_SEPARATOR) - else: - base_token_symbol = market_info["baseTokenMeta"]["symbol"] - quote_token_symbol = market_info["quoteTokenMeta"]["symbol"] - base_token = self._token_representation( - symbol=base_token_symbol, token_meta=market_info["baseTokenMeta"], denom=market_info["baseDenom"], tokens_by_denom=tokens_by_denom, tokens_by_symbol=tokens_by_symbol, ) quote_token = self._token_representation( - symbol=quote_token_symbol, token_meta=market_info["quoteTokenMeta"], denom=market_info["quoteDenom"], tokens_by_denom=tokens_by_denom, @@ -2704,10 +2694,7 @@ async def _initialize_tokens_and_markets(self): ) for market_info in valid_markets: - quote_token_symbol = market_info["quoteTokenMeta"]["symbol"] - quote_token = self._token_representation( - symbol=quote_token_symbol, token_meta=market_info["quoteTokenMeta"], denom=market_info["quoteDenom"], tokens_by_denom=tokens_by_denom, @@ -2769,7 +2756,6 @@ async def _initialize_tokens_and_markets(self): def _token_representation( self, - symbol: str, token_meta: Dict[str, Any], denom: str, tokens_by_denom: Dict[str, Token], @@ -2777,14 +2763,14 @@ def _token_representation( ) -> Token: if denom not in tokens_by_denom: unique_symbol = denom - for symbol_candidate in [symbol, token_meta["symbol"], token_meta["name"]]: + for symbol_candidate in [token_meta["symbol"], token_meta["name"]]: if symbol_candidate not in tokens_by_symbol: unique_symbol = symbol_candidate break token = Token( name=token_meta["name"], - symbol=symbol, + symbol=token_meta["symbol"], denom=denom, address=token_meta["address"], decimals=token_meta["decimals"], From ca0c2ce636c8b0663bf72f067223610c33aa973c Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 6 Feb 2024 16:50:12 -0300 Subject: [PATCH 05/44] (feat) Refactored all examples to remove references to private keys. Added the use of `dotenv` to load private keys into environment variables. Removed `asyncio` package dependency --- examples/SendToInjective.py | 7 +- examples/chain_client/0_LocalOrderHash.py | 8 +- .../13_MsgIncreasePositionMargin.py | 7 +- examples/chain_client/15_MsgWithdraw.py | 7 +- .../chain_client/16_MsgSubaccountTransfer.py | 7 +- .../chain_client/17_MsgBatchUpdateOrders.py | 7 +- examples/chain_client/18_MsgBid.py | 7 +- examples/chain_client/19_MsgGrant.py | 12 +- examples/chain_client/1_MsgSend.py | 7 +- examples/chain_client/20_MsgExec.py | 12 +- examples/chain_client/21_MsgRevoke.py | 12 +- examples/chain_client/22_MsgSendToEth.py | 7 +- .../chain_client/23_MsgRelayPriceFeedPrice.py | 7 +- examples/chain_client/24_MsgRewardsOptOut.py | 7 +- examples/chain_client/25_MsgDelegate.py | 7 +- .../26_MsgWithdrawDelegatorReward.py | 7 +- examples/chain_client/27_Grants.py | 9 +- examples/chain_client/2_MsgDeposit.py | 9 +- examples/chain_client/30_ExternalTransfer.py | 7 +- .../31_MsgCreateBinaryOptionsLimitOrder.py | 7 +- .../32_MsgCreateBinaryOptionsMarketOrder.py | 7 +- .../33_MsgCancelBinaryOptionsOrder.py | 7 +- .../34_MsgAdminUpdateBinaryOptionsMarket.py | 7 +- .../35_MsgInstantBinaryOptionsMarketLaunch.py | 7 +- .../chain_client/36_MsgRelayProviderPrices.py | 7 +- .../chain_client/3_MsgCreateSpotLimitOrder.py | 7 +- .../chain_client/40_MsgExecuteContract.py | 7 +- .../chain_client/41_MsgCreateInsuranceFund.py | 7 +- examples/chain_client/42_MsgUnderwrite.py | 7 +- .../chain_client/43_MsgRequestRedemption.py | 7 +- .../chain_client/44_MessageBroadcaster.py | 7 +- ...45_MessageBroadcasterWithGranteeAccount.py | 10 +- .../46_MessageBroadcasterWithoutSimulation.py | 7 +- ...sterWithGranteeAccountWithoutSimulation.py | 9 +- ...8_WithdrawValidatorCommissionAndRewards.py | 7 +- .../4_MsgCreateSpotMarketOrder.py | 7 +- examples/chain_client/5_MsgCancelSpotOrder.py | 7 +- .../6_MsgCreateDerivativeLimitOrder.py | 7 +- examples/chain_client/71_CreateDenom.py | 7 +- examples/chain_client/72_MsgMint.py | 7 +- examples/chain_client/73_MsgBurn.py | 7 +- .../chain_client/74_MsgSetDenomMetadata.py | 7 +- examples/chain_client/75_MsgChangeAdmin.py | 7 +- .../76_MsgExecuteContractCompat.py | 7 +- .../chain_client/77_MsgLiquidatePosition.py | 7 +- .../7_MsgCreateDerivativeMarketOrder.py | 7 +- .../8_MsgCancelDerivativeOrder.py | 7 +- poetry.lock | 2350 ++++++++--------- pyinjective/denoms_devnet.ini | 13 + pyinjective/denoms_mainnet.ini | 116 +- pyinjective/denoms_testnet.ini | 2 +- pyproject.toml | 4 +- 52 files changed, 1461 insertions(+), 1378 deletions(-) diff --git a/examples/SendToInjective.py b/examples/SendToInjective.py index b03988b4..23469642 100644 --- a/examples/SendToInjective.py +++ b/examples/SendToInjective.py @@ -1,16 +1,21 @@ import asyncio import json +import os + +import dotenv from pyinjective.core.network import Network from pyinjective.sendtocosmos import Peggo async def main() -> None: + dotenv.load_dotenv() + private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: testnet, mainnet network = Network.testnet() peggo_composer = Peggo(network=network.string()) - private_key = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" ethereum_endpoint = "https://eth-goerli.g.alchemy.com/v2/q-7JVv4mTfsNh1y_djKkKn3maRBGILLL" maxFeePerGas_Gwei = 4 diff --git a/examples/chain_client/0_LocalOrderHash.py b/examples/chain_client/0_LocalOrderHash.py index c81c3e2e..a25398c6 100644 --- a/examples/chain_client/0_LocalOrderHash.py +++ b/examples/chain_client/0_LocalOrderHash.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.async_client import AsyncClient from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE from pyinjective.core.network import Network @@ -10,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/13_MsgIncreasePositionMargin.py b/examples/chain_client/13_MsgIncreasePositionMargin.py index 27d42884..f54910f8 100644 --- a/examples/chain_client/13_MsgIncreasePositionMargin.py +++ b/examples/chain_client/13_MsgIncreasePositionMargin.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/15_MsgWithdraw.py b/examples/chain_client/15_MsgWithdraw.py index 9fc1e359..a8c267d8 100644 --- a/examples/chain_client/15_MsgWithdraw.py +++ b/examples/chain_client/15_MsgWithdraw.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/16_MsgSubaccountTransfer.py b/examples/chain_client/16_MsgSubaccountTransfer.py index 5a18b1dd..d87eb0ed 100644 --- a/examples/chain_client/16_MsgSubaccountTransfer.py +++ b/examples/chain_client/16_MsgSubaccountTransfer.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/17_MsgBatchUpdateOrders.py b/examples/chain_client/17_MsgBatchUpdateOrders.py index 25147452..557ffe46 100644 --- a/examples/chain_client/17_MsgBatchUpdateOrders.py +++ b/examples/chain_client/17_MsgBatchUpdateOrders.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/18_MsgBid.py b/examples/chain_client/18_MsgBid.py index 9e51e075..8e5f8d5e 100644 --- a/examples/chain_client/18_MsgBid.py +++ b/examples/chain_client/18_MsgBid.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/19_MsgGrant.py b/examples/chain_client/19_MsgGrant.py index 0d00d489..32a82fe7 100644 --- a/examples/chain_client/19_MsgGrant.py +++ b/examples/chain_client/19_MsgGrant.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) @@ -30,8 +36,8 @@ async def main() -> None: # GENERIC AUTHZ msg = composer.MsgGrantGeneric( - granter="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", - grantee="inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku", + granter=address.to_acc_bech32(), + grantee=grantee_public_address, msg_type="/injective.exchange.v1beta1.MsgCreateSpotLimitOrder", expire_in=31536000, # 1 year ) diff --git a/examples/chain_client/1_MsgSend.py b/examples/chain_client/1_MsgSend.py index 9b9651f7..6389c8be 100644 --- a/examples/chain_client/1_MsgSend.py +++ b/examples/chain_client/1_MsgSend.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/20_MsgExec.py b/examples/chain_client/20_MsgExec.py index a2876d6a..d5ff2dc5 100644 --- a/examples/chain_client/20_MsgExec.py +++ b/examples/chain_client/20_MsgExec.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,10 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") + granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,15 +26,15 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) # prepare tx msg market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - grantee = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku" - granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + grantee = address.to_acc_bech32() + granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) msg0 = composer.MsgCreateSpotLimitOrder( diff --git a/examples/chain_client/21_MsgRevoke.py b/examples/chain_client/21_MsgRevoke.py index 2cafab7f..82663004 100644 --- a/examples/chain_client/21_MsgRevoke.py +++ b/examples/chain_client/21_MsgRevoke.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,15 +25,15 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) # prepare tx msg msg = composer.MsgRevoke( - granter="inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku", - grantee="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + granter=address.to_acc_bech32(), + grantee=grantee_public_address, msg_type="/injective.exchange.v1beta1.MsgCreateSpotLimitOrder", ) diff --git a/examples/chain_client/22_MsgSendToEth.py b/examples/chain_client/22_MsgSendToEth.py index 1cb1e677..59bdc877 100644 --- a/examples/chain_client/22_MsgSendToEth.py +++ b/examples/chain_client/22_MsgSendToEth.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv import requests from grpc import RpcError @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/23_MsgRelayPriceFeedPrice.py b/examples/chain_client/23_MsgRelayPriceFeedPrice.py index 38b389de..cc7055c9 100644 --- a/examples/chain_client/23_MsgRelayPriceFeedPrice.py +++ b/examples/chain_client/23_MsgRelayPriceFeedPrice.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/24_MsgRewardsOptOut.py b/examples/chain_client/24_MsgRewardsOptOut.py index bbc8d348..5fa2f429 100644 --- a/examples/chain_client/24_MsgRewardsOptOut.py +++ b/examples/chain_client/24_MsgRewardsOptOut.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/25_MsgDelegate.py b/examples/chain_client/25_MsgDelegate.py index dc95f035..ada14ce0 100644 --- a/examples/chain_client/25_MsgDelegate.py +++ b/examples/chain_client/25_MsgDelegate.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/26_MsgWithdrawDelegatorReward.py b/examples/chain_client/26_MsgWithdrawDelegatorReward.py index 77210421..f9370c23 100644 --- a/examples/chain_client/26_MsgWithdrawDelegatorReward.py +++ b/examples/chain_client/26_MsgWithdrawDelegatorReward.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/27_Grants.py b/examples/chain_client/27_Grants.py index 331980af..9ab27f22 100644 --- a/examples/chain_client/27_Grants.py +++ b/examples/chain_client/27_Grants.py @@ -1,14 +1,19 @@ import asyncio +import os + +import dotenv from pyinjective.async_client import AsyncClient from pyinjective.core.network import Network async def main() -> None: + dotenv.load_dotenv() + granter = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + grantee = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + network = Network.testnet() client = AsyncClient(network) - granter = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku" - grantee = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" msg_type_url = "/injective.exchange.v1beta1.MsgCreateDerivativeLimitOrder" authorizations = await client.fetch_grants(granter=granter, grantee=grantee, msg_type_url=msg_type_url) print(authorizations) diff --git a/examples/chain_client/2_MsgDeposit.py b/examples/chain_client/2_MsgDeposit.py index 9c137b49..80587c55 100644 --- a/examples/chain_client/2_MsgDeposit.py +++ b/examples/chain_client/2_MsgDeposit.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,8 +12,11 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet - network = Network.testnet(node="sentry") + network = Network.testnet() # initialize grpc client client = AsyncClient(network) @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/30_ExternalTransfer.py b/examples/chain_client/30_ExternalTransfer.py index d657c15a..7ab6e0f2 100644 --- a/examples/chain_client/30_ExternalTransfer.py +++ b/examples/chain_client/30_ExternalTransfer.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py index 137529ea..57f5537b 100644 --- a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py +++ b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -12,6 +14,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -21,7 +26,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py index 67004f17..473e8e53 100644 --- a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py +++ b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py index 2631ab26..15159f00 100644 --- a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py +++ b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py index d9eb1e18..55c308be 100644 --- a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py +++ b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py index e0881db5..7e865320 100644 --- a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py +++ b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/36_MsgRelayProviderPrices.py b/examples/chain_client/36_MsgRelayProviderPrices.py index 0fb26b4f..4ee5fc3f 100644 --- a/examples/chain_client/36_MsgRelayProviderPrices.py +++ b/examples/chain_client/36_MsgRelayProviderPrices.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/3_MsgCreateSpotLimitOrder.py index 8d873354..dd06672a 100644 --- a/examples/chain_client/3_MsgCreateSpotLimitOrder.py +++ b/examples/chain_client/3_MsgCreateSpotLimitOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/40_MsgExecuteContract.py b/examples/chain_client/40_MsgExecuteContract.py index fef42954..f2d1b719 100644 --- a/examples/chain_client/40_MsgExecuteContract.py +++ b/examples/chain_client/40_MsgExecuteContract.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/41_MsgCreateInsuranceFund.py b/examples/chain_client/41_MsgCreateInsuranceFund.py index b402dc26..74f94bfa 100644 --- a/examples/chain_client/41_MsgCreateInsuranceFund.py +++ b/examples/chain_client/41_MsgCreateInsuranceFund.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/42_MsgUnderwrite.py b/examples/chain_client/42_MsgUnderwrite.py index 9a14b3ce..20c65a64 100644 --- a/examples/chain_client/42_MsgUnderwrite.py +++ b/examples/chain_client/42_MsgUnderwrite.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/43_MsgRequestRedemption.py b/examples/chain_client/43_MsgRequestRedemption.py index 6ba0fe31..4413044b 100644 --- a/examples/chain_client/43_MsgRequestRedemption.py +++ b/examples/chain_client/43_MsgRequestRedemption.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/44_MessageBroadcaster.py b/examples/chain_client/44_MessageBroadcaster.py index a9bb1f68..114a8700 100644 --- a/examples/chain_client/44_MessageBroadcaster.py +++ b/examples/chain_client/44_MessageBroadcaster.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network @@ -8,10 +11,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py b/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py index 59c04af2..8c0166e2 100644 --- a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py +++ b/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.async_client import AsyncClient from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -9,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") + granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) @@ -18,7 +25,6 @@ async def main() -> None: await client.sync_timeout_height() # load account - private_key_in_hexa = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() @@ -30,7 +36,7 @@ async def main() -> None: # prepare tx msg market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) diff --git a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py b/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py index 908a4579..e6e87c5a 100644 --- a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py +++ b/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network @@ -8,10 +11,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( network=network, diff --git a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py b/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py index ebae28ab..b95114b7 100644 --- a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py +++ b/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.async_client import AsyncClient from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -9,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") + granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) @@ -18,7 +25,6 @@ async def main() -> None: await client.sync_timeout_height() # load account - private_key_in_hexa = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() @@ -30,7 +36,6 @@ async def main() -> None: # prepare tx msg market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) diff --git a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py b/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py index b46ca371..2f67f6c4 100644 --- a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py +++ b/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + """For a validator to withdraw his rewards & commissions simultaneously""" # select network: local, testnet, mainnet network = Network.testnet() @@ -22,7 +27,7 @@ async def main() -> None: # load account # private key is that from the validator's wallet - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/4_MsgCreateSpotMarketOrder.py index d689362f..06a42a96 100644 --- a/examples/chain_client/4_MsgCreateSpotMarketOrder.py +++ b/examples/chain_client/4_MsgCreateSpotMarketOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/5_MsgCancelSpotOrder.py b/examples/chain_client/5_MsgCancelSpotOrder.py index a6fabc01..63167309 100644 --- a/examples/chain_client/5_MsgCancelSpotOrder.py +++ b/examples/chain_client/5_MsgCancelSpotOrder.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py index b875d339..e46f1acb 100644 --- a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/71_CreateDenom.py b/examples/chain_client/71_CreateDenom.py index 61e76dbf..0662439a 100644 --- a/examples/chain_client/71_CreateDenom.py +++ b/examples/chain_client/71_CreateDenom.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/72_MsgMint.py b/examples/chain_client/72_MsgMint.py index e96bad93..d38449be 100644 --- a/examples/chain_client/72_MsgMint.py +++ b/examples/chain_client/72_MsgMint.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/73_MsgBurn.py b/examples/chain_client/73_MsgBurn.py index cff5a1b4..441f4ee8 100644 --- a/examples/chain_client/73_MsgBurn.py +++ b/examples/chain_client/73_MsgBurn.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/74_MsgSetDenomMetadata.py b/examples/chain_client/74_MsgSetDenomMetadata.py index 58fa30c0..367649e0 100644 --- a/examples/chain_client/74_MsgSetDenomMetadata.py +++ b/examples/chain_client/74_MsgSetDenomMetadata.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( network=network, diff --git a/examples/chain_client/75_MsgChangeAdmin.py b/examples/chain_client/75_MsgChangeAdmin.py index 2abc6ec6..d1a1ba46 100644 --- a/examples/chain_client/75_MsgChangeAdmin.py +++ b/examples/chain_client/75_MsgChangeAdmin.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( network=network, diff --git a/examples/chain_client/76_MsgExecuteContractCompat.py b/examples/chain_client/76_MsgExecuteContractCompat.py index 978ff115..892c125f 100644 --- a/examples/chain_client/76_MsgExecuteContractCompat.py +++ b/examples/chain_client/76_MsgExecuteContractCompat.py @@ -1,6 +1,8 @@ import asyncio import json +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/77_MsgLiquidatePosition.py b/examples/chain_client/77_MsgLiquidatePosition.py index 65e7f12b..6dcbacfb 100644 --- a/examples/chain_client/77_MsgLiquidatePosition.py +++ b/examples/chain_client/77_MsgLiquidatePosition.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py index 744b5ff9..e7e06c62 100644 --- a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py +++ b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/8_MsgCancelDerivativeOrder.py b/examples/chain_client/8_MsgCancelDerivativeOrder.py index b784b536..6a59167a 100644 --- a/examples/chain_client/8_MsgCancelDerivativeOrder.py +++ b/examples/chain_client/8_MsgCancelDerivativeOrder.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/poetry.lock b/poetry.lock index c7b1c317..72bd53e3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,87 +2,87 @@ [[package]] name = "aiohttp" -version = "3.9.1" +version = "3.9.3" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.8" files = [ - {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1f80197f8b0b846a8d5cf7b7ec6084493950d0882cc5537fb7b96a69e3c8590"}, - {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c72444d17777865734aa1a4d167794c34b63e5883abb90356a0364a28904e6c0"}, - {file = "aiohttp-3.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9b05d5cbe9dafcdc733262c3a99ccf63d2f7ce02543620d2bd8db4d4f7a22f83"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c4fa235d534b3547184831c624c0b7c1e262cd1de847d95085ec94c16fddcd5"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:289ba9ae8e88d0ba16062ecf02dd730b34186ea3b1e7489046fc338bdc3361c4"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bff7e2811814fa2271be95ab6e84c9436d027a0e59665de60edf44e529a42c1f"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81b77f868814346662c96ab36b875d7814ebf82340d3284a31681085c051320f"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b9c7426923bb7bd66d409da46c41e3fb40f5caf679da624439b9eba92043fa6"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8d44e7bf06b0c0a70a20f9100af9fcfd7f6d9d3913e37754c12d424179b4e48f"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22698f01ff5653fe66d16ffb7658f582a0ac084d7da1323e39fd9eab326a1f26"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ca7ca5abfbfe8d39e653870fbe8d7710be7a857f8a8386fc9de1aae2e02ce7e4"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:8d7f98fde213f74561be1d6d3fa353656197f75d4edfbb3d94c9eb9b0fc47f5d"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5216b6082c624b55cfe79af5d538e499cd5f5b976820eac31951fb4325974501"}, - {file = "aiohttp-3.9.1-cp310-cp310-win32.whl", hash = "sha256:0e7ba7ff228c0d9a2cd66194e90f2bca6e0abca810b786901a569c0de082f489"}, - {file = "aiohttp-3.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:c7e939f1ae428a86e4abbb9a7c4732bf4706048818dfd979e5e2839ce0159f23"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:df9cf74b9bc03d586fc53ba470828d7b77ce51b0582d1d0b5b2fb673c0baa32d"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ecca113f19d5e74048c001934045a2b9368d77b0b17691d905af18bd1c21275e"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8cef8710fb849d97c533f259103f09bac167a008d7131d7b2b0e3a33269185c0"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea94403a21eb94c93386d559bce297381609153e418a3ffc7d6bf772f59cc35"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91c742ca59045dce7ba76cab6e223e41d2c70d79e82c284a96411f8645e2afff"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c93b7c2e52061f0925c3382d5cb8980e40f91c989563d3d32ca280069fd6a87"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee2527134f95e106cc1653e9ac78846f3a2ec1004cf20ef4e02038035a74544d"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11ff168d752cb41e8492817e10fb4f85828f6a0142b9726a30c27c35a1835f01"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b8c3a67eb87394386847d188996920f33b01b32155f0a94f36ca0e0c635bf3e3"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c7b5d5d64e2a14e35a9240b33b89389e0035e6de8dbb7ffa50d10d8b65c57449"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:69985d50a2b6f709412d944ffb2e97d0be154ea90600b7a921f95a87d6f108a2"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:c9110c06eaaac7e1f5562caf481f18ccf8f6fdf4c3323feab28a93d34cc646bd"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737e69d193dac7296365a6dcb73bbbf53bb760ab25a3727716bbd42022e8d7a"}, - {file = "aiohttp-3.9.1-cp311-cp311-win32.whl", hash = "sha256:4ee8caa925aebc1e64e98432d78ea8de67b2272252b0a931d2ac3bd876ad5544"}, - {file = "aiohttp-3.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:a34086c5cc285be878622e0a6ab897a986a6e8bf5b67ecb377015f06ed316587"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f800164276eec54e0af5c99feb9494c295118fc10a11b997bbb1348ba1a52065"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:500f1c59906cd142d452074f3811614be04819a38ae2b3239a48b82649c08821"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0b0a6a36ed7e164c6df1e18ee47afbd1990ce47cb428739d6c99aaabfaf1b3af"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69da0f3ed3496808e8cbc5123a866c41c12c15baaaead96d256477edf168eb57"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:176df045597e674fa950bf5ae536be85699e04cea68fa3a616cf75e413737eb5"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b796b44111f0cab6bbf66214186e44734b5baab949cb5fb56154142a92989aeb"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f27fdaadce22f2ef950fc10dcdf8048407c3b42b73779e48a4e76b3c35bca26c"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcb6532b9814ea7c5a6a3299747c49de30e84472fa72821b07f5a9818bce0f66"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:54631fb69a6e44b2ba522f7c22a6fb2667a02fd97d636048478db2fd8c4e98fe"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4b4c452d0190c5a820d3f5c0f3cd8a28ace48c54053e24da9d6041bf81113183"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:cae4c0c2ca800c793cae07ef3d40794625471040a87e1ba392039639ad61ab5b"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:565760d6812b8d78d416c3c7cfdf5362fbe0d0d25b82fed75d0d29e18d7fc30f"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54311eb54f3a0c45efb9ed0d0a8f43d1bc6060d773f6973efd90037a51cd0a3f"}, - {file = "aiohttp-3.9.1-cp312-cp312-win32.whl", hash = "sha256:85c3e3c9cb1d480e0b9a64c658cd66b3cfb8e721636ab8b0e746e2d79a7a9eed"}, - {file = "aiohttp-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:11cb254e397a82efb1805d12561e80124928e04e9c4483587ce7390b3866d213"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8a22a34bc594d9d24621091d1b91511001a7eea91d6652ea495ce06e27381f70"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:598db66eaf2e04aa0c8900a63b0101fdc5e6b8a7ddd805c56d86efb54eb66672"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c9376e2b09895c8ca8b95362283365eb5c03bdc8428ade80a864160605715f1"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41473de252e1797c2d2293804e389a6d6986ef37cbb4a25208de537ae32141dd"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c5857612c9813796960c00767645cb5da815af16dafb32d70c72a8390bbf690"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffcd828e37dc219a72c9012ec44ad2e7e3066bec6ff3aaa19e7d435dbf4032ca"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:219a16763dc0294842188ac8a12262b5671817042b35d45e44fd0a697d8c8361"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f694dc8a6a3112059258a725a4ebe9acac5fe62f11c77ac4dcf896edfa78ca28"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bcc0ea8d5b74a41b621ad4a13d96c36079c81628ccc0b30cfb1603e3dfa3a014"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:90ec72d231169b4b8d6085be13023ece8fa9b1bb495e4398d847e25218e0f431"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:cf2a0ac0615842b849f40c4d7f304986a242f1e68286dbf3bd7a835e4f83acfd"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:0e49b08eafa4f5707ecfb321ab9592717a319e37938e301d462f79b4e860c32a"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2c59e0076ea31c08553e868cec02d22191c086f00b44610f8ab7363a11a5d9d8"}, - {file = "aiohttp-3.9.1-cp38-cp38-win32.whl", hash = "sha256:4831df72b053b1eed31eb00a2e1aff6896fb4485301d4ccb208cac264b648db4"}, - {file = "aiohttp-3.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:3135713c5562731ee18f58d3ad1bf41e1d8883eb68b363f2ffde5b2ea4b84cc7"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cfeadf42840c1e870dc2042a232a8748e75a36b52d78968cda6736de55582766"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70907533db712f7aa791effb38efa96f044ce3d4e850e2d7691abd759f4f0ae0"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cdefe289681507187e375a5064c7599f52c40343a8701761c802c1853a504558"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7481f581251bb5558ba9f635db70908819caa221fc79ee52a7f58392778c636"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49f0c1b3c2842556e5de35f122fc0f0b721334ceb6e78c3719693364d4af8499"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d406b01a9f5a7e232d1b0d161b40c05275ffbcbd772dc18c1d5a570961a1ca4"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d8e4450e7fe24d86e86b23cc209e0023177b6d59502e33807b732d2deb6975f"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c0266cd6f005e99f3f51e583012de2778e65af6b73860038b968a0a8888487a"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab221850108a4a063c5b8a70f00dd7a1975e5a1713f87f4ab26a46e5feac5a0e"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c88a15f272a0ad3d7773cf3a37cc7b7d077cbfc8e331675cf1346e849d97a4e5"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:237533179d9747080bcaad4d02083ce295c0d2eab3e9e8ce103411a4312991a0"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:02ab6006ec3c3463b528374c4cdce86434e7b89ad355e7bf29e2f16b46c7dd6f"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04fa38875e53eb7e354ece1607b1d2fdee2d175ea4e4d745f6ec9f751fe20c7c"}, - {file = "aiohttp-3.9.1-cp39-cp39-win32.whl", hash = "sha256:82eefaf1a996060602f3cc1112d93ba8b201dbf5d8fd9611227de2003dddb3b7"}, - {file = "aiohttp-3.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:9b05d33ff8e6b269e30a7957bd3244ffbce2a7a35a81b81c382629b80af1a8bf"}, - {file = "aiohttp-3.9.1.tar.gz", hash = "sha256:8fc49a87ac269d4529da45871e2ffb6874e87779c3d0e2ccd813c0899221239d"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"}, + {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"}, + {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"}, + {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"}, + {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"}, + {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"}, + {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"}, + {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"}, + {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"}, + {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"}, + {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"}, + {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"}, ] [package.dependencies] @@ -110,17 +110,6 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" -[[package]] -name = "annotated-types" -version = "0.6.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -files = [ - {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, - {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, -] - [[package]] name = "asn1crypto" version = "1.5.1" @@ -143,36 +132,24 @@ files = [ {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, ] -[[package]] -name = "asyncio" -version = "3.4.3" -description = "reference implementation of PEP 3156" -optional = false -python-versions = "*" -files = [ - {file = "asyncio-3.4.3-cp33-none-win32.whl", hash = "sha256:b62c9157d36187eca799c378e572c969f0da87cd5fc42ca372d92cdb06e7e1de"}, - {file = "asyncio-3.4.3-cp33-none-win_amd64.whl", hash = "sha256:c46a87b48213d7464f22d9a497b9eef8c1928b68320a2fa94240f969f6fec08c"}, - {file = "asyncio-3.4.3-py3-none-any.whl", hash = "sha256:c4d18b22701821de07bd6aea8b53d21449ec0ec5680645e5317062ea21817d2d"}, - {file = "asyncio-3.4.3.tar.gz", hash = "sha256:83360ff8bc97980e4ff25c964c7bd3923d333d177aa4f7fb736b019f26c7cb41"}, -] - [[package]] name = "attrs" -version = "23.1.0" +version = "23.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, - {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, ] [package.extras] cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]", "pre-commit"] +dev = ["attrs[tests]", "pre-commit"] docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] [[package]] name = "base58" @@ -216,160 +193,164 @@ coincurve = ">=15.0,<19" [[package]] name = "bitarray" -version = "2.8.5" +version = "2.9.2" description = "efficient arrays of booleans -- C extension" optional = false python-versions = "*" files = [ - {file = "bitarray-2.8.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5970beec89c26e85874311b3928db3ca61d91badbc4cd18ef712cb456f933b45"}, - {file = "bitarray-2.8.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:641d1a437e9121c56cf6efdc73636d1a62d8150e75146ad23b2dc6723e1117d7"}, - {file = "bitarray-2.8.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:519cc61816c5d00af2f6178baa11fc51cf5fd0a6a7af78c6c06e1218f01b54d0"}, - {file = "bitarray-2.8.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30d2dc6b4e46804f74c7e8c416562f6af6707b164fcaef19cf8335019c1353db"}, - {file = "bitarray-2.8.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4581f6e579ea351a6c2bb1eeea2261cccbf2a06271230072025b82bc9b1d64cb"}, - {file = "bitarray-2.8.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e67d02e498bca3941d4a1af8f11d9a84d9876a6573a7c67717fd3a34f2b421c"}, - {file = "bitarray-2.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbead40d87d27c407c547ea1ded4c64832e972cba9a5241ffb76ed3d3bf874f6"}, - {file = "bitarray-2.8.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:63b4c16a4e4f9332d489d2385a9fe919cbcf67b250b200f9d3a6d0fd1f26f16f"}, - {file = "bitarray-2.8.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b54a89fce51b4f329e6aa03d9993d1a07b640bb5b555e7c0c81feafead01e2e4"}, - {file = "bitarray-2.8.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:638f666598f1e0a2b261c48788772e8273772e0a2987263ab71466967543ed84"}, - {file = "bitarray-2.8.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:39fbfbc325768e8a74499b9616622768aeccbfa8837ed2dd458dd74dc3b7443c"}, - {file = "bitarray-2.8.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0610a823be0e512567f73648d61938a120d8594ac6ca1b04fad1e8fe72522dcd"}, - {file = "bitarray-2.8.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8d990ee363ae8845f5af742fd02b4eb6b784f0279cc0ae85f3da3e81b6eb0050"}, - {file = "bitarray-2.8.5-cp310-cp310-win32.whl", hash = "sha256:46dec1b3aff26af53e92680f9a439f56e8968f832d8aca0f8e131d2be2ae6cc1"}, - {file = "bitarray-2.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:b90b86d445a5c904eff92b890cb7c36a77f5a91ef8d1744933b9cf478f46f6e5"}, - {file = "bitarray-2.8.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09ba2973929dc405d269296a0ae2d2d45fd3286149d62f883067b0ab8cb6ba30"}, - {file = "bitarray-2.8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ca41d7ccb5f4036abac0c94072e1b07206b071c51068e064bbd6be6627f34cbb"}, - {file = "bitarray-2.8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51de323b17b4f1312be20497d4cee0ae092903c70ad752d66ae44037e0a65be5"}, - {file = "bitarray-2.8.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b65f373a11d256021ee6ad802544f4c04e3d7ad971a96117f828a3bf65fc27"}, - {file = "bitarray-2.8.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea443f107d2ee95ac21f3acc080006dd27a8304d2e95adeb9e256133993d3381"}, - {file = "bitarray-2.8.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c2f890beff3b0fa4e89bcfe73b844f38bb3407d25bcc036d21e4ae319bfe4ac"}, - {file = "bitarray-2.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8211533d5f1c73470f6b656ceebba72d555adb00a01a9359f4182cb100b01d"}, - {file = "bitarray-2.8.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3944d548e24eecbfa19353b14c20abe9bc1b07267b8045ad9f2f82fdac8f1d9f"}, - {file = "bitarray-2.8.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:da0281f041680306c582f0a0d65f4ab0547fa313687f24017f3e6ecf57097cbb"}, - {file = "bitarray-2.8.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9c4f3adc0370dcb4dcabb81a4eabd40fdc0e15afbded0ab214d7046c5669bb51"}, - {file = "bitarray-2.8.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:751ec37d423121ccaf0a5ca0f216ff7caef4d86773cb40ec67b400a187dee092"}, - {file = "bitarray-2.8.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f42103b470c9a7fa33122b880ea0fc4f4ed53b38fd84915e0d4b0e569ff8397d"}, - {file = "bitarray-2.8.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:36d3ad647b7c9b51bb84aa709cd467bbb202c6e678ff4871b743c2464c4888ef"}, - {file = "bitarray-2.8.5-cp311-cp311-win32.whl", hash = "sha256:fabf6dd12627aee02a0f06a73a7379fbe493569e8206d2e4c3755c36d37acba0"}, - {file = "bitarray-2.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:6b6338e07c923791b761138664b3aa36995cdb6378d12500829d449bdbf0ce6c"}, - {file = "bitarray-2.8.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9a9dbee82c3f53898d6ff339c31c753c5888cf33ee90e6668a2425602121291e"}, - {file = "bitarray-2.8.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ccd7849ca9eb89ea9d2b07be55ec8dbbc1984258775002373ba39bc2cf17b4ea"}, - {file = "bitarray-2.8.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e67f0d205acbd8d4c550d4d97a6c7ea21459a38bbdba2392fb62ff7414f25550"}, - {file = "bitarray-2.8.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:916398e3792fcfe46d88d078aa38cd41ab7a1b808481d10ad6cdc2693772241d"}, - {file = "bitarray-2.8.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3365867e5c910c1fd527175cca7539788df138375523acda3a65663d1e35ea7d"}, - {file = "bitarray-2.8.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2292aa678a6f158feb1eb295ece26a0f487e0094cd43483390cc2883bd0ca551"}, - {file = "bitarray-2.8.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fd1f1d3b35ecc004eb18fc36d1dbc2df75e8b759e2e74e7cf6983ca0c6a8a7e"}, - {file = "bitarray-2.8.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:964e1057bc94c287d0b04be281a4ceaa14182b3a8fd58c3be75251a377021745"}, - {file = "bitarray-2.8.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a8a9006ae20dbe30e6d7d3d8464171d8ee0924799281c13389c73b841fe2f104"}, - {file = "bitarray-2.8.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:468a69f8406f8a39a87b765d4a08f18758204853c5daa52f5e43662ca973895a"}, - {file = "bitarray-2.8.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:a576df7dfa2c86067697a016a6c66fef1477e0fc41b90ccd80331aec62c8ace6"}, - {file = "bitarray-2.8.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:330ef4733c254fb166b183c83ec9571bf90049e2d04d4efda160660b95cf9820"}, - {file = "bitarray-2.8.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:166a1c8381a006f420ff3772e59d79f4b50f3638d76056fe01c8e1e08b7ce0bd"}, - {file = "bitarray-2.8.5-cp312-cp312-win32.whl", hash = "sha256:181e6ff49d844cefdc32920ad3c734b120646e949a9a3ce51e8aa78aeb1cdf1b"}, - {file = "bitarray-2.8.5-cp312-cp312-win_amd64.whl", hash = "sha256:f56f662421003c04d4fb3c82ac046ee77f69d65719c045821257cf40cc498402"}, - {file = "bitarray-2.8.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:47ee48d9aba59a14abbbd96372e4155461b76d19b461d57287d6eb26c5406bf9"}, - {file = "bitarray-2.8.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9d66bb8d159b0d19d733f4e6c3512a63228a6ab1f4654d2dca6736ede62fb83"}, - {file = "bitarray-2.8.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2f3fbaa9a1fff8e6784c2340e9678a52fc6bd9d6ee438d065133a543267e0348"}, - {file = "bitarray-2.8.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a2c5722425dac1b5366da783d32dbfb7d09961ade934210b9428c60c05418f11"}, - {file = "bitarray-2.8.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca0034064b66209b07c5df1fa39697890e6305b36e4560d9958713ae0c23698"}, - {file = "bitarray-2.8.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bac4e535bd5e82d83676a6492c3486e93837771e1183a3bbf4557ac5bda715a4"}, - {file = "bitarray-2.8.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:52702217c0d84d24601d45f652d41c0881d1a66c772e3094b7dadec4181462f8"}, - {file = "bitarray-2.8.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:a9bfe75add2d6684414bb8182ff55b4a3a7b9157f54675e87098a66e6d3e03d4"}, - {file = "bitarray-2.8.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5589324d8f762ede479bdb9cbd8f2a14dfa4c378209fe6c4807ca9b12c06d0dc"}, - {file = "bitarray-2.8.5-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ccf1b41554245c16ae50a9838637190f590f9748fe319b7271154bfa9295805a"}, - {file = "bitarray-2.8.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:923a536d6bcfb20402b88d73c1f08c1d1b7cb0d026a8207a72df3c38c7223d40"}, - {file = "bitarray-2.8.5-cp36-cp36m-win32.whl", hash = "sha256:75083026b7969600c14cd40019ce09192f17222fdad6010df9ea3fa48e949089"}, - {file = "bitarray-2.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:801144db5c237f25deafc910d7dc3cd008be5f104da0d937fe9db7cdabe8fdf8"}, - {file = "bitarray-2.8.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b03a23b7f69877441bcdecb94182491ab827fe635079861aa28ecc4da0477f27"}, - {file = "bitarray-2.8.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5948915f572757c0b6a44116baff0f416256a163e339e43dd46846d82105354"}, - {file = "bitarray-2.8.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7914054d5d5ecfdfaf55de026cacc4a998f79143f6d96782449f7927e0340258"}, - {file = "bitarray-2.8.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef01042e1b4eb87d367e81265b5c037066652dd20ce81f3ff519a0f023786ecd"}, - {file = "bitarray-2.8.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a24a91b5637d0398b61903e3f33b87007b2ec16ddfb9687e294453c18b1a1bef"}, - {file = "bitarray-2.8.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9aa571e45bf4df5f1e99b38c4c7af5a840a51c5b0f601beebd8d8160b035581"}, - {file = "bitarray-2.8.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ce48a3abc7cfb9153bba5e198cc58ae2b31f164631b685d67ba10e9a21ef12f6"}, - {file = "bitarray-2.8.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:99acc9b8474443fb13d077adf33caa6e7e17bc16510faeb8aa5f8d80947fcc02"}, - {file = "bitarray-2.8.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:9a39b4479eea530f7a2738db1845529a0cfb7b4eef1d200ae812cd416fbec4b7"}, - {file = "bitarray-2.8.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:f4aa5f3601967d90ee780b1fbf783db2aba30afbc967656d10e257f817c9a7f0"}, - {file = "bitarray-2.8.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:eee881c7b4c2eb05e2316aa7e0d417b8f51a745c7a6e14de0223fcf36c60205a"}, - {file = "bitarray-2.8.5-cp37-cp37m-win32.whl", hash = "sha256:8340b3044fc421e5c14997aa346a015fdf9e7cf39a4ed29559fa78a93efcc18c"}, - {file = "bitarray-2.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:0802aed38f0b39974cad73457640c7577995f62873318e978cb2fed0b7c6ce9b"}, - {file = "bitarray-2.8.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c2640070dc06f146cc4098001cf0c857f4fab5d9fbc5edbacc52001751f15349"}, - {file = "bitarray-2.8.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ee2e373890fc8a287c393cb619e85650c388f9915b44a9592dd8f06026d8cad1"}, - {file = "bitarray-2.8.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:55492cb5362e9e7648503adb6507d8d49e7b55b847217a331243b7ad26929190"}, - {file = "bitarray-2.8.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d51e1e5a94813c33bf27eeac3009c6021b303a8591719dab8c47cd0ee75fbca0"}, - {file = "bitarray-2.8.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:19d5c20a66046690e981ed624889378fe4e02cd302eb3d8c05d082d53751443c"}, - {file = "bitarray-2.8.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bc481046d824002511e9c3355fef700c4831a9ac6bea57643b43843e4fd27aa6"}, - {file = "bitarray-2.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70506cbd34d396a58592e9b651fc2ef4d4956b8c99cc7c732be638d9a5864202"}, - {file = "bitarray-2.8.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd2c6d472363980235000304bb777f1c4c9d13534aee7629c7f6d11c3b17f16f"}, - {file = "bitarray-2.8.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d85a8da1683faca4b5a6d270778c69e47faee44effda9148df49546551518db"}, - {file = "bitarray-2.8.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:49cfeef05f49afb71308537189766e39fabddb296906e6a3433303c2df6ccaa4"}, - {file = "bitarray-2.8.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f29678680d54f849b933dbea217cc3e13999e11637ad834cfc147dd7de68b46e"}, - {file = "bitarray-2.8.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5daff9edebdb5b0bdc0461af37e9de00e5d3bafb9be0e41c7575095e9f60119b"}, - {file = "bitarray-2.8.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e8639cde035b32f11c51b12e6caea96bdc0f28ef212a38405319df62747c9e3c"}, - {file = "bitarray-2.8.5-cp38-cp38-win32.whl", hash = "sha256:2eaf80e8560cb9061b8da21be4898086e9da26ffbfa0997704eca1f2838a10ed"}, - {file = "bitarray-2.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:e374452faec82b88ff50c63ba7c423524b9a02cfb5ad76eb3d32166fc6277d30"}, - {file = "bitarray-2.8.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:037c239573cad4d95623dcb2d840fa01a28e0120e9c5195b9cb7b9d6c8aa6a9b"}, - {file = "bitarray-2.8.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:80e68f44a69f9b8f69aef6858a4ffdefcfb46342789804c9b8d3c6fdda0f7247"}, - {file = "bitarray-2.8.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e3c322c4cda8fee03132d80ced2d44e1a9f07a1ab69f22f4fc7e8ba34fe30f93"}, - {file = "bitarray-2.8.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb3692aed783e351598c3b9f5180b0912c75fe6538f6e324f372b4204b12f0cc"}, - {file = "bitarray-2.8.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e094247c49c9048391b2b5a21705059428d47b4bf5c4d353cf602bd61762565f"}, - {file = "bitarray-2.8.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23fe468ae57652c873d4b2d4db7cde0f8fb38bf315be20edaa5bf2e130f2ca4b"}, - {file = "bitarray-2.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6cb14bff7f528ee18f68ab89c0790cc2d6c73272ba6d0675edfa7692470c867d"}, - {file = "bitarray-2.8.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6b71825f4478dfae301e60d7067d82196fc5f7eee05fdad35880fba9a89f9684"}, - {file = "bitarray-2.8.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:94e8a8703914930f5a673b27b0a221d2819c4805699e7b545e675e86cae7bcab"}, - {file = "bitarray-2.8.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4739948b067d29d2a9858943329f9d984b239f912f6141c2ead4806e4470d2b3"}, - {file = "bitarray-2.8.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:a60db40f0a86fa1e88ed8a94580f0ae638035238c5aaaf4f29f5867dd0765266"}, - {file = "bitarray-2.8.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:c867d02724d57ae7f799a304d15ef05c675860c7a67ee2903ad88b40cfe40105"}, - {file = "bitarray-2.8.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:84ee826d1e35ddedd65b5af9820e240a0d7a4c5b6e16078ae2965541bcd1f922"}, - {file = "bitarray-2.8.5-cp39-cp39-win32.whl", hash = "sha256:86b6a64aa854b4c108e3c76388fb0acc859c424ca321260cb2ea83bbfb40985c"}, - {file = "bitarray-2.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:1f270dc9476c3c6ac7d865f625ff4e9ec09f544a44ce58c31dd4d989534de758"}, - {file = "bitarray-2.8.5-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:17b61aadf929550279414f638a28e99ef0048c88951dc9fe045734362fb40218"}, - {file = "bitarray-2.8.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eae1eb20a574b02eca607379b9a609f25669e3c532fa1c2576355a5dbee0b274"}, - {file = "bitarray-2.8.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c0be77c7a6b4e90e53c004b11f683fab839b0bf6eecd15f978c85053e5826dc"}, - {file = "bitarray-2.8.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc239f6a9c2877245f60b1b1a9a381c3df14db704bdabac91a28b49b9093c4ba"}, - {file = "bitarray-2.8.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cf6d0e91a45371fe4d8de172a2455a5925a4958bea2785f194dde0cd80711098"}, - {file = "bitarray-2.8.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:dd43180febbf28bc63b40a4f5d8627f26f468d2e5e0a9c637aa86fd94144a5d4"}, - {file = "bitarray-2.8.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:152ecc17e42cab84d1564815377a361008e04cd035f9959c2f7ba1cd2d70a952"}, - {file = "bitarray-2.8.5-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c73350d5d251ae7fce68d3a0677c6fd5d123760643bf46e4830994f1a2d03e61"}, - {file = "bitarray-2.8.5-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ea70b2b7a3e9ad76b05e664851a8c406c9e81231ada519bb8392a970fae981a"}, - {file = "bitarray-2.8.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:a6229bcc61f2d932dbd5e52d9ffb6a128ac77a2acfcdf91c6e9a32a700de857d"}, - {file = "bitarray-2.8.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f6367c58f3f6716d593fd756a85d9daae5d96a9ce6daa2a3ba683e2b37d155f6"}, - {file = "bitarray-2.8.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5a1230393ed10d6c525ba5dd86a5b11cc375b933470920fa63df2f859769ad6"}, - {file = "bitarray-2.8.5-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c414bda2f9e7537e549ef0d81512c70950ad319e303646eb5ace7f123777ab52"}, - {file = "bitarray-2.8.5-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da894ec250fd035fa0443ffd910071bfa49609cd2c0a7e0d527d4a9d907d9381"}, - {file = "bitarray-2.8.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:980852f02631280e303b8d8e42f6d42838b9b73353df0da2e2bad110275b5cfc"}, - {file = "bitarray-2.8.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b1a6b53a320766c4ad85aa22ad4590b1099d43fc0cf7d9c9f2c3d17a5d7027d9"}, - {file = "bitarray-2.8.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e5401deb5c40c0aebc9da543be2133ba63901f1296d060c3d2fdea6aa2735b7"}, - {file = "bitarray-2.8.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97b0ad82100af78abd58e21b8af5ddcad517c2b2ef1f35be3cefcbc5240d7094"}, - {file = "bitarray-2.8.5-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e189393da3b8883970db6b4a00a2cc8f13405dc9dc215fc28567d5b17a2a3fa"}, - {file = "bitarray-2.8.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0f3d171f01aa40aa393d4dd21d515fd5992bb92149852f9528f8db95ae384ee3"}, - {file = "bitarray-2.8.5.tar.gz", hash = "sha256:b7564fd218cc4479f7f0106d341e096f78907b47865aeeff702c807df1927c01"}, + {file = "bitarray-2.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:917905de565d9576eb20f53c797c15ba88b9f4f19728acabec8d01eee1d3756a"}, + {file = "bitarray-2.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b35bfcb08b7693ab4bf9059111a6e9f14e07d57ac93cd967c420db58ab9b71e1"}, + {file = "bitarray-2.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ea1923d2e7880f9e1959e035da661767b5a2e16a45dfd57d6aa831e8b65ee1bf"}, + {file = "bitarray-2.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0b63a565e8a311cc8348ff1262d5784df0f79d64031d546411afd5dd7ef67d"}, + {file = "bitarray-2.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cf0620da2b81946d28c0b16f3e3704d38e9837d85ee4f0652816e2609aaa4fed"}, + {file = "bitarray-2.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:79a9b8b05f2876c7195a2b698c47528e86a73c61ea203394ff8e7a4434bda5c8"}, + {file = "bitarray-2.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:345c76b349ff145549652436235c5532e5bfe9db690db6f0a6ad301c62b9ef21"}, + {file = "bitarray-2.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e2936f090bf3f4d1771f44f9077ebccdbc0415d2b598d51a969afcb519df505"}, + {file = "bitarray-2.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f9346e98fc2abcef90b942973087e2462af6d3e3710e82938078d3493f7fef52"}, + {file = "bitarray-2.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e6ec283d4741befb86e8c3ea2e9ac1d17416c956d392107e45263e736954b1f7"}, + {file = "bitarray-2.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:962892646599529917ef26266091e4cb3077c88b93c3833a909d68dcc971c4e3"}, + {file = "bitarray-2.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e8da5355d7d75a52df5b84750989e34e39919ec7e59fafc4c104cc1607ab2d31"}, + {file = "bitarray-2.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:603e7d640e54ad764d2b4da6b61e126259af84f253a20f512dd10689566e5478"}, + {file = "bitarray-2.9.2-cp310-cp310-win32.whl", hash = "sha256:f00079f8e69d75c2a417de7961a77612bb77ef46c09bc74607d86de4740771ef"}, + {file = "bitarray-2.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:1bb33673e7f7190a65f0a940c1ef63266abdb391f4a3e544a47542d40a81f536"}, + {file = "bitarray-2.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fe71fd4b76380c2772f96f1e53a524da7063645d647a4fcd3b651bdd80ca0f2e"}, + {file = "bitarray-2.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d527172919cdea1e13994a66d9708a80c3d33dedcf2f0548e4925e600fef3a3a"}, + {file = "bitarray-2.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:052c5073bdcaa9dd10628d99d37a2f33ec09364b86dd1f6281e2d9f8d3db3060"}, + {file = "bitarray-2.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e064caa55a6ed493aca1eda06f8b3f689778bc780a75e6ad7724642ba5dc62f7"}, + {file = "bitarray-2.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:508069a04f658210fdeee85a7a0ca84db4bcc110cbb1d21f692caa13210f24a7"}, + {file = "bitarray-2.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4da73ebd537d75fa7bccfc2228fcaedea0803f21dd9d0bf0d3b67fef3c4af294"}, + {file = "bitarray-2.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cb378eaa65cd43098f11ff5d27e48ee3b956d2c00d2d6b5bfc2a09fe183be47"}, + {file = "bitarray-2.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d14c790b91f6cbcd9b718f88ed737c78939980c69ac8c7f03dd7e60040c12951"}, + {file = "bitarray-2.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7eea9318293bc0ea6447e9ebfba600a62f3428bea7e9c6d42170ae4f481dbab3"}, + {file = "bitarray-2.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b76ffec27c7450b8a334f967366a9ebadaea66ee43f5b530c12861b1a991f503"}, + {file = "bitarray-2.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:76b76a07d4ee611405045c6950a1e24c4362b6b44808d4ad6eea75e0dbc59af4"}, + {file = "bitarray-2.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:c7d16beeaaab15b075990cd26963d6b5b22e8c5becd131781514a00b8bdd04bd"}, + {file = "bitarray-2.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60df43e868a615c7e15117a1e1c2e5e11f48f6457280eba6ddf8fbefbec7da99"}, + {file = "bitarray-2.9.2-cp311-cp311-win32.whl", hash = "sha256:e788608ed7767b7b3bbde6d49058bccdf94df0de9ca75d13aa99020cc7e68095"}, + {file = "bitarray-2.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:a23397da092ef0a8cfe729571da64c2fc30ac18243caa82ac7c4f965087506ff"}, + {file = "bitarray-2.9.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:90e3a281ffe3897991091b7c46fca38c2675bfd4399ffe79dfeded6c52715436"}, + {file = "bitarray-2.9.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bed637b674db5e6c8a97a4a321e3e4d73e72d50b5c6b29950008a93069cc64cd"}, + {file = "bitarray-2.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e49066d251dbbe4e6e3a5c3937d85b589e40e2669ad0eef41a00f82ec17d844b"}, + {file = "bitarray-2.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4344e96642e2211fb3a50558feff682c31563a4c64529a931769d40832ca79"}, + {file = "bitarray-2.9.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aeb60962ec4813c539a59fbd4f383509c7222b62c3fb1faa76b54943a613e33a"}, + {file = "bitarray-2.9.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed0f7982f10581bb16553719e5e8f933e003f5b22f7d25a68bdb30fac630a6ff"}, + {file = "bitarray-2.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c71d1cabdeee0cdda4669168618f0e46b7dace207b29da7b63aaa1adc2b54081"}, + {file = "bitarray-2.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0ef2d0a6f1502d38d911d25609b44c6cc27bee0a4363dd295df78b075041b60"}, + {file = "bitarray-2.9.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:6f71d92f533770fb027388b35b6e11988ab89242b883f48a6fe7202d238c61f8"}, + {file = "bitarray-2.9.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ba0734aa300757c924f3faf8148e1b8c247176a0ac8e16aefdf9c1eb19e868f7"}, + {file = "bitarray-2.9.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:d91406f413ccbf4af6ab5ae7bc78f772a95609f9ddd14123db36ef8c37116d95"}, + {file = "bitarray-2.9.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:87abb7f80c0a042f3fe8e5264da1a2756267450bb602110d5327b8eaff7682e7"}, + {file = "bitarray-2.9.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b558ce85579b51a2e38703877d1e93b7728a7af664dd45a34e833534f0b755d"}, + {file = "bitarray-2.9.2-cp312-cp312-win32.whl", hash = "sha256:dac2399ee2889fbdd3472bfc2ede74c34cceb1ccf29a339964281a16eb1d3188"}, + {file = "bitarray-2.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:48a30d718d1a6dfc22a49547450107abe8f4afdf2abdcbe76eb9ed88edc49498"}, + {file = "bitarray-2.9.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2c6be1b651fad8f3adb7a5aa12c65b612cd9b89530969af941844ae680f7d981"}, + {file = "bitarray-2.9.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5b399ae6ab975257ec359f03b48fc00b1c1cd109471e41903548469b8feae5c"}, + {file = "bitarray-2.9.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b3543c8a1cb286ad105f11c25d8d0f712f41c5c55f90be39f0e5a1376c7d0b0"}, + {file = "bitarray-2.9.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:03adaacb79e2fb8f483ab3a67665eec53bb3fd0cd5dbd7358741aef124688db3"}, + {file = "bitarray-2.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ae5b0657380d2581e13e46864d147a52c1e2bbac9f59b59c576e42fa7d10cf0"}, + {file = "bitarray-2.9.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c1f4bf6ea8eb9d7f30808c2e9894237a96650adfecbf5f3643862dc5982f89e"}, + {file = "bitarray-2.9.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a8873089be2aa15494c0f81af1209f6e1237d762c5065bc4766c1b84321e1b50"}, + {file = "bitarray-2.9.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:677e67f50e2559efc677a4366707070933ad5418b8347a603a49a070890b19bc"}, + {file = "bitarray-2.9.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:a620d8ce4ea2f1c73c6b6b1399e14cb68c6915e2be3fad5808c2998ed55b4acf"}, + {file = "bitarray-2.9.2-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:64115ccabbdbe279c24c367b629c6b1d3da9ed36c7420129e27c338a3971bfee"}, + {file = "bitarray-2.9.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:5d6fb422772e75385b76ad1c52f45a68bd4efafd8be8d0061c11877be74c4d43"}, + {file = "bitarray-2.9.2-cp36-cp36m-win32.whl", hash = "sha256:852e202875dd6dfd6139ce7ec4e98dac2b17d8d25934dc99900831e81c3adaef"}, + {file = "bitarray-2.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:7dfefdcb0dc6a3ba9936063cec65a74595571b375beabe18742b3d91d087eefd"}, + {file = "bitarray-2.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b306c4cf66912511422060f7f5e1149c8bdb404f8e00e600561b0749fdd45659"}, + {file = "bitarray-2.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a09c4f81635408e3387348f415521d4b94198c562c23330f560596a6aaa26eaf"}, + {file = "bitarray-2.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5361413fd2ecfdf44dc8f065177dc6aba97fa80a91b815586cb388763acf7f8d"}, + {file = "bitarray-2.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e8a9475d415ef1eaae7942df6f780fa4dcd48fce32825eda591a17abba869299"}, + {file = "bitarray-2.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9b87baa7bfff9a5878fcc1bffe49ecde6e647a72a64b39a69cd8a2992a43a34"}, + {file = "bitarray-2.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb6b86cfdfc503e92cb71c68766a24565359136961642504a7cc9faf936d9c88"}, + {file = "bitarray-2.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cd56b8ae87ebc71bcacbd73615098e8a8de952ecbb5785b6b4e2b07da8a06e1f"}, + {file = "bitarray-2.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3fa909cfd675004aed8b4cc9df352415933656e0155a6209d878b7cb615c787e"}, + {file = "bitarray-2.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b069ca9bf728e0c5c5b60e00a89df9af34cc170c695c3bfa3b372d8f40288efb"}, + {file = "bitarray-2.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:6067f2f07a7121749858c7daa93c8774325c91590b3e81a299621e347740c2ae"}, + {file = "bitarray-2.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:321841cdad1dd0f58fe62e80e9c9c7531f8ebf8be93f047401e930dc47425b1e"}, + {file = "bitarray-2.9.2-cp37-cp37m-win32.whl", hash = "sha256:54e16e32e60973bb83c315de9975bc1bcfc9bd50bb13001c31da159bc49b0ca1"}, + {file = "bitarray-2.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:f4dcadb7b8034aa3491ee8f5a69b3d9ba9d7d1e55c3cc1fc45be313e708277f8"}, + {file = "bitarray-2.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c8919fdbd3bb596b104388b56ae4b266eb28da1f2f7dff2e1f9334a21840fe96"}, + {file = "bitarray-2.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eb7a9d8a2e400a1026de341ad48e21670a6261a75b06df162c5c39b0d0e7c8f4"}, + {file = "bitarray-2.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6ec84668dd7b937874a2b2c293cd14ba84f37be0d196dead852e0ada9815d807"}, + {file = "bitarray-2.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2de9a31c34e543ae089fd2a5ced01292f725190e379921384f695e2d7184bd3"}, + {file = "bitarray-2.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9521f49ae121a17c0a41e5112249e6fa7f6a571245b1118de81fb86e7c1bc1ce"}, + {file = "bitarray-2.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6cc6545d6d76542aee3d18c1c9485fb7b9812b8df4ebe52c4535ec42081b48f"}, + {file = "bitarray-2.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:856bbe1616425f71c0df5ef2e8755e878d9504d5a531acba58ab4273c52c117a"}, + {file = "bitarray-2.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4bba8042ea6ab331ade91bc435d81ad72fddb098e49108610b0ce7780c14e68"}, + {file = "bitarray-2.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a035da89c959d98afc813e3c62f052690d67cfd55a36592f25d734b70de7d4b0"}, + {file = "bitarray-2.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6d70b1579da7fb71be5a841a1f965d19aca0ef27f629cfc07d06b09aafd0a333"}, + {file = "bitarray-2.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:405b83bed28efaae6d86b6ab287c75712ead0adbfab2a1075a1b7ab47dad4d62"}, + {file = "bitarray-2.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7eb8be687c50da0b397d5e0ab7ca200b5ebb639e79a9f5e285851d1944c94be9"}, + {file = "bitarray-2.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eceb551dfeaf19c609003a69a0cf8264b0efd7abc3791a11dfabf4788daf0d19"}, + {file = "bitarray-2.9.2-cp38-cp38-win32.whl", hash = "sha256:bb198c6ed1edbcdaf3d1fa3c9c9d1cdb7e179a5134ef5ee660b53cdec43b34e7"}, + {file = "bitarray-2.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:648d2f2685590b0103c67a937c2fb9e09bcc8dfb166f0c7c77bd341902a6f5b3"}, + {file = "bitarray-2.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ea816dc8f8e65841a8bbdd30e921edffeeb6f76efe6a1eb0da147b60d539d1cf"}, + {file = "bitarray-2.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4d0e32530f941c41eddfc77600ec89b65184cb909c549336463a738fab3ed285"}, + {file = "bitarray-2.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4a22266fb416a3b6c258bf7f83c9fe531ba0b755a56986a81ad69dc0f3bcc070"}, + {file = "bitarray-2.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc6d3e80dd8239850f2604833ff3168b28909c8a9357abfed95632cccd17e3e7"}, + {file = "bitarray-2.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f135e804986b12bf14f2cd1eb86674c47dea86c4c5f0fa13c88978876b97ebe6"}, + {file = "bitarray-2.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87580c7f7d14f7ec401eda7adac1e2a25e95153e9c339872c8ae61b3208819a1"}, + {file = "bitarray-2.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64b433e26993127732ac7b66a7821b2537c3044355798de7c5fcb0af34b8296f"}, + {file = "bitarray-2.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e497c535f2a9b68c69d36631bf2dba243e05eb343b00b9c7bbdc8c601c6802d"}, + {file = "bitarray-2.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e40b3cb9fa1edb4e0175d7c06345c49c7925fe93e39ef55ecb0bc40c906b0c09"}, + {file = "bitarray-2.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f2f8692f95c9e377eb19ca519d30d1f884b02feb7e115f798de47570a359e43f"}, + {file = "bitarray-2.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f0b84fc50b6dbeced4fa390688c07c10a73222810fb0e08392bd1a1b8259de36"}, + {file = "bitarray-2.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d656ad38c942e38a470ddbce26b5020e08e1a7ea86b8fd413bb9024b5189993a"}, + {file = "bitarray-2.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6ab0f1dbfe5070db98771a56aa14797595acd45a1af9eadfb193851a270e7996"}, + {file = "bitarray-2.9.2-cp39-cp39-win32.whl", hash = "sha256:0a99b23ac845a9ea3157782c97465e6ae026fe0c7c4c1ed1d88f759fd6ea52d9"}, + {file = "bitarray-2.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:9bbcfc7c279e8d74b076e514e669b683f77b4a2a328585b3f16d4c5259c91222"}, + {file = "bitarray-2.9.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:43847799461d8ba71deb4d97b47250c2c2fb66d82cd3cb8b4caf52bb97c03034"}, + {file = "bitarray-2.9.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f44381b0a4bdf64416082f4f0e7140377ae962c0ced6f983c6d7bbfc034040"}, + {file = "bitarray-2.9.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a484061616fb4b158b80789bd3cb511f399d2116525a8b29b6334c68abc2310f"}, + {file = "bitarray-2.9.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ff9e38356cc803e06134cf8ae9758e836ccd1b793135ef3db53c7c5d71e93bc"}, + {file = "bitarray-2.9.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b44105792fbdcfbda3e26ee88786790fda409da4c71f6c2b73888108cf8f062f"}, + {file = "bitarray-2.9.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7e913098de169c7fc890638ce5e171387363eb812579e637c44261460ac00aa2"}, + {file = "bitarray-2.9.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6fe315355cdfe3ed22ef355b8bdc81a805ca4d0949d921576560e5b227a1112"}, + {file = "bitarray-2.9.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f708e91fdbe443f3bec2df394ed42328fb9b0446dff5cb4199023ac6499e09fd"}, + {file = "bitarray-2.9.2-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b7b09489b71f9f1f64c0fa0977e250ec24500767dab7383ba9912495849cadf"}, + {file = "bitarray-2.9.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:128cc3488176145b9b137fdcf54c1c201809bbb8dd30b260ee40afe915843b43"}, + {file = "bitarray-2.9.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:21f21e7f56206be346bdbda2a6bdb2165a5e6a11821f88fd4911c5a6bbbdc7e2"}, + {file = "bitarray-2.9.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f4dd3af86dd8a617eb6464622fb64ca86e61ce99b59b5c35d8cd33f9c30603d"}, + {file = "bitarray-2.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6465de861aff7a2559f226b37982007417eab8c3557543879987f58b453519bd"}, + {file = "bitarray-2.9.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbaf2bb71d6027152d603f1d5f31e0dfd5e50173d06f877bec484e5396d4594b"}, + {file = "bitarray-2.9.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2f32948c86e0d230a296686db28191b67ed229756f84728847daa0c7ab7406e3"}, + {file = "bitarray-2.9.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be94e5a685e60f9d24532af8fe5c268002e9016fa80272a94727f435de3d1003"}, + {file = "bitarray-2.9.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5cc9381fd54f3c23ae1039f977bfd6d041a5c3c1518104f616643c3a5a73b15"}, + {file = "bitarray-2.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd926e8ae4d1ed1ac4a8f37212a62886292f692bc1739fde98013bf210c2d175"}, + {file = "bitarray-2.9.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:461a3dafb9d5fda0bb3385dc507d78b1984b49da3fe4c6d56c869a54373b7008"}, + {file = "bitarray-2.9.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:393cb27fd859af5fd9c16eb26b1c59b17b390ff66b3ae5d0dd258270191baf13"}, + {file = "bitarray-2.9.2.tar.gz", hash = "sha256:a8f286a51a32323715d77755ed959f94bef13972e9a2fe71b609e40e6d27957e"}, ] [[package]] name = "black" -version = "23.11.0" +version = "23.12.1" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ - {file = "black-23.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dbea0bb8575c6b6303cc65017b46351dc5953eea5c0a59d7b7e3a2d2f433a911"}, - {file = "black-23.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:412f56bab20ac85927f3a959230331de5614aecda1ede14b373083f62ec24e6f"}, - {file = "black-23.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d136ef5b418c81660ad847efe0e55c58c8208b77a57a28a503a5f345ccf01394"}, - {file = "black-23.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:6c1cac07e64433f646a9a838cdc00c9768b3c362805afc3fce341af0e6a9ae9f"}, - {file = "black-23.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cf57719e581cfd48c4efe28543fea3d139c6b6f1238b3f0102a9c73992cbb479"}, - {file = "black-23.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:698c1e0d5c43354ec5d6f4d914d0d553a9ada56c85415700b81dc90125aac244"}, - {file = "black-23.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:760415ccc20f9e8747084169110ef75d545f3b0932ee21368f63ac0fee86b221"}, - {file = "black-23.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:58e5f4d08a205b11800332920e285bd25e1a75c54953e05502052738fe16b3b5"}, - {file = "black-23.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:45aa1d4675964946e53ab81aeec7a37613c1cb71647b5394779e6efb79d6d187"}, - {file = "black-23.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c44b7211a3a0570cc097e81135faa5f261264f4dfaa22bd5ee2875a4e773bd6"}, - {file = "black-23.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a9acad1451632021ee0d146c8765782a0c3846e0e0ea46659d7c4f89d9b212b"}, - {file = "black-23.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:fc7f6a44d52747e65a02558e1d807c82df1d66ffa80a601862040a43ec2e3142"}, - {file = "black-23.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7f622b6822f02bfaf2a5cd31fdb7cd86fcf33dab6ced5185c35f5db98260b055"}, - {file = "black-23.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:250d7e60f323fcfc8ea6c800d5eba12f7967400eb6c2d21ae85ad31c204fb1f4"}, - {file = "black-23.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5133f5507007ba08d8b7b263c7aa0f931af5ba88a29beacc4b2dc23fcefe9c06"}, - {file = "black-23.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:421f3e44aa67138ab1b9bfbc22ee3780b22fa5b291e4db8ab7eee95200726b07"}, - {file = "black-23.11.0-py3-none-any.whl", hash = "sha256:54caaa703227c6e0c87b76326d0862184729a69b73d3b7305b6288e1d830067e"}, - {file = "black-23.11.0.tar.gz", hash = "sha256:4c68855825ff432d197229846f971bc4d6666ce90492e5b02013bcaca4d9ab05"}, + {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, + {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, + {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, + {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, + {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, + {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, + {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, + {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, + {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, + {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, + {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, + {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, + {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, + {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, + {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, + {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, + {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, + {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, + {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, + {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, + {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, + {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, ] [package.dependencies] @@ -383,30 +364,19 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] +d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] -[[package]] -name = "cerberus" -version = "1.3.5" -description = "Lightweight, extensible schema and data validation tool for Pythondictionaries." -optional = false -python-versions = "*" -files = [ - {file = "Cerberus-1.3.5-py3-none-any.whl", hash = "sha256:7649a5815024d18eb7c6aa5e7a95355c649a53aacfc9b050e9d0bf6bfa2af372"}, - {file = "Cerberus-1.3.5.tar.gz", hash = "sha256:81011e10266ef71b6ec6d50e60171258a5b134d69f8fb387d16e4936d0d47642"}, -] - [[package]] name = "certifi" -version = "2023.11.17" +version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, - {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] [[package]] @@ -665,63 +635,63 @@ files = [ [[package]] name = "coverage" -version = "7.3.2" +version = "7.4.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"}, - {file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"}, - {file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"}, - {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"}, - {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"}, - {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"}, - {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"}, - {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"}, - {file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"}, - {file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"}, - {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"}, - {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"}, - {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"}, - {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"}, - {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"}, - {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"}, - {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"}, - {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"}, - {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"}, - {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"}, - {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"}, - {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"}, - {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"}, - {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"}, - {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"}, - {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"}, - {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"}, - {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"}, - {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"}, - {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"}, - {file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"}, - {file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"}, - {file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"}, - {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"}, - {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"}, - {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"}, - {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"}, - {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"}, - {file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"}, - {file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"}, - {file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"}, - {file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"}, - {file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"}, - {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"}, - {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"}, - {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"}, - {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"}, - {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"}, - {file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"}, - {file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"}, - {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"}, - {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"}, + {file = "coverage-7.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:077d366e724f24fc02dbfe9d946534357fda71af9764ff99d73c3c596001bbd7"}, + {file = "coverage-7.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0193657651f5399d433c92f8ae264aff31fc1d066deee4b831549526433f3f61"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d17bbc946f52ca67adf72a5ee783cd7cd3477f8f8796f59b4974a9b59cacc9ee"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3277f5fa7483c927fe3a7b017b39351610265308f5267ac6d4c2b64cc1d8d25"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dceb61d40cbfcf45f51e59933c784a50846dc03211054bd76b421a713dcdf19"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6008adeca04a445ea6ef31b2cbaf1d01d02986047606f7da266629afee982630"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c61f66d93d712f6e03369b6a7769233bfda880b12f417eefdd4f16d1deb2fc4c"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9bb62fac84d5f2ff523304e59e5c439955fb3b7f44e3d7b2085184db74d733b"}, + {file = "coverage-7.4.1-cp310-cp310-win32.whl", hash = "sha256:f86f368e1c7ce897bf2457b9eb61169a44e2ef797099fb5728482b8d69f3f016"}, + {file = "coverage-7.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:869b5046d41abfea3e381dd143407b0d29b8282a904a19cb908fa24d090cc018"}, + {file = "coverage-7.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8ffb498a83d7e0305968289441914154fb0ef5d8b3157df02a90c6695978295"}, + {file = "coverage-7.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3cacfaefe6089d477264001f90f55b7881ba615953414999c46cc9713ff93c8c"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d6850e6e36e332d5511a48a251790ddc545e16e8beaf046c03985c69ccb2676"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18e961aa13b6d47f758cc5879383d27b5b3f3dcd9ce8cdbfdc2571fe86feb4dd"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfd1e1b9f0898817babf840b77ce9fe655ecbe8b1b327983df485b30df8cc011"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6b00e21f86598b6330f0019b40fb397e705135040dbedc2ca9a93c7441178e74"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:536d609c6963c50055bab766d9951b6c394759190d03311f3e9fcf194ca909e1"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7ac8f8eb153724f84885a1374999b7e45734bf93a87d8df1e7ce2146860edef6"}, + {file = "coverage-7.4.1-cp311-cp311-win32.whl", hash = "sha256:f3771b23bb3675a06f5d885c3630b1d01ea6cac9e84a01aaf5508706dba546c5"}, + {file = "coverage-7.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:9d2f9d4cc2a53b38cabc2d6d80f7f9b7e3da26b2f53d48f05876fef7956b6968"}, + {file = "coverage-7.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f68ef3660677e6624c8cace943e4765545f8191313a07288a53d3da188bd8581"}, + {file = "coverage-7.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23b27b8a698e749b61809fb637eb98ebf0e505710ec46a8aa6f1be7dc0dc43a6"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e3424c554391dc9ef4a92ad28665756566a28fecf47308f91841f6c49288e66"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0860a348bf7004c812c8368d1fc7f77fe8e4c095d661a579196a9533778e156"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe558371c1bdf3b8fa03e097c523fb9645b8730399c14fe7721ee9c9e2a545d3"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3468cc8720402af37b6c6e7e2a9cdb9f6c16c728638a2ebc768ba1ef6f26c3a1"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:02f2edb575d62172aa28fe00efe821ae31f25dc3d589055b3fb64d51e52e4ab1"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ca6e61dc52f601d1d224526360cdeab0d0712ec104a2ce6cc5ccef6ed9a233bc"}, + {file = "coverage-7.4.1-cp312-cp312-win32.whl", hash = "sha256:ca7b26a5e456a843b9b6683eada193fc1f65c761b3a473941efe5a291f604c74"}, + {file = "coverage-7.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:85ccc5fa54c2ed64bd91ed3b4a627b9cce04646a659512a051fa82a92c04a448"}, + {file = "coverage-7.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8bdb0285a0202888d19ec6b6d23d5990410decb932b709f2b0dfe216d031d218"}, + {file = "coverage-7.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:918440dea04521f499721c039863ef95433314b1db00ff826a02580c1f503e45"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:379d4c7abad5afbe9d88cc31ea8ca262296480a86af945b08214eb1a556a3e4d"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b094116f0b6155e36a304ff912f89bbb5067157aff5f94060ff20bbabdc8da06"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f5968608b1fe2a1d00d01ad1017ee27efd99b3437e08b83ded9b7af3f6f766"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:10e88e7f41e6197ea0429ae18f21ff521d4f4490aa33048f6c6f94c6045a6a75"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a4a3907011d39dbc3e37bdc5df0a8c93853c369039b59efa33a7b6669de04c60"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d224f0c4c9c98290a6990259073f496fcec1b5cc613eecbd22786d398ded3ad"}, + {file = "coverage-7.4.1-cp38-cp38-win32.whl", hash = "sha256:23f5881362dcb0e1a92b84b3c2809bdc90db892332daab81ad8f642d8ed55042"}, + {file = "coverage-7.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:a07f61fc452c43cd5328b392e52555f7d1952400a1ad09086c4a8addccbd138d"}, + {file = "coverage-7.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8e738a492b6221f8dcf281b67129510835461132b03024830ac0e554311a5c54"}, + {file = "coverage-7.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46342fed0fff72efcda77040b14728049200cbba1279e0bf1188f1f2078c1d70"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9641e21670c68c7e57d2053ddf6c443e4f0a6e18e547e86af3fad0795414a628"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aeb2c2688ed93b027eb0d26aa188ada34acb22dceea256d76390eea135083950"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d12c923757de24e4e2110cf8832d83a886a4cf215c6e61ed506006872b43a6d1"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0491275c3b9971cdbd28a4595c2cb5838f08036bca31765bad5e17edf900b2c7"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8dfc5e195bbef80aabd81596ef52a1277ee7143fe419efc3c4d8ba2754671756"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a78b656a4d12b0490ca72651fe4d9f5e07e3c6461063a9b6265ee45eb2bdd35"}, + {file = "coverage-7.4.1-cp39-cp39-win32.whl", hash = "sha256:f90515974b39f4dea2f27c0959688621b46d96d5a626cf9c53dbc653a895c05c"}, + {file = "coverage-7.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:64e723ca82a84053dd7bfcc986bdb34af8d9da83c521c19d6b472bc6880e191a"}, + {file = "coverage-7.4.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:32a8d985462e37cfdab611a6f95b09d7c091d07668fdc26e47a725ee575fe166"}, + {file = "coverage-7.4.1.tar.gz", hash = "sha256:1ed4b95480952b1a26d863e546fa5094564aa0065e1e5f0d4d0041f293251d04"}, ] [package.dependencies] @@ -732,104 +702,115 @@ toml = ["tomli"] [[package]] name = "cytoolz" -version = "0.12.2" +version = "0.12.3" description = "Cython implementation of Toolz: High performance functional utilities" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "cytoolz-0.12.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bff49986c9bae127928a2f9fd6313146a342bfae8292f63e562f872bd01b871"}, - {file = "cytoolz-0.12.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:908c13f305d34322e11b796de358edaeea47dd2d115c33ca22909c5e8fb036fd"}, - {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:735147aa41b8eeb104da186864b55e2a6623c758000081d19c93d759cd9523e3"}, - {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d352d4de060604e605abdc5c8a5d0429d5f156cb9866609065d3003454d4cea"}, - {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:89247ac220031a4f9f689688bcee42b38fd770d4cce294e5d914afc53b630abe"}, - {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9070ae35c410d644e6df98a8f69f3ed2807e657d0df2a26b2643127cbf6944a5"}, - {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:843500cd3e4884b92fd4037912bc42d5f047108d2c986d36352e880196d465b0"}, - {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6a93644d7996fd696ab7f1f466cd75d718d0a00d5c8118b9fe8c64231dc1f85e"}, - {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:96796594c770bc6587376e74ddc7d9c982d68f47116bb69d90873db5e0ea88b6"}, - {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:48425107fbb1af3f0f2410c004f16be10ffc9374358e5600b57fa543f46f8def"}, - {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:cde6dbb788a4cbc4a80a72aa96386ba4c2b17bdfff3ace0709799adbe16d6476"}, - {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:68ae7091cc73a752f0b938f15bb193de80ca5edf5ae2ea6360d93d3e9228357b"}, - {file = "cytoolz-0.12.2-cp310-cp310-win32.whl", hash = "sha256:997b7e0960072f6bb445402da162f964ea67387b9f18bda2361edcc026e13597"}, - {file = "cytoolz-0.12.2-cp310-cp310-win_amd64.whl", hash = "sha256:663911786dcde3e4a5d88215c722c531c7548903dc07d418418c0d1c768072c0"}, - {file = "cytoolz-0.12.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a7d8b869ded171f6cdf584fc2fc6ae03b30a0e1e37a9daf213a59857a62ed90"}, - {file = "cytoolz-0.12.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9b28787eaf2174e68f0acb3c66f9c6b98bdfeb0930c0d0b08e1941c7aedc8d27"}, - {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00547da587f124b32b072ce52dd5e4b37cf199fedcea902e33c67548523e4678"}, - {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:275d53fd769df2102d6c9fc98e553bd8a9a38926f54d6b20cf29f0dd00bf3b75"}, - {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5556acde785a61d4cf8b8534ae109b023cbd2f9df65ee2afbe070be47c410f8c"}, - {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b41a85b9b9a2530b72b0d3d10e383fc3c2647ae88169d557d5e216f881860318"}, - {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:673d6e9e3aa86949343b46ac2b7be266c36e07ce77fa1d40f349e6987a814d6e"}, - {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81e6a9a8fda78a2f4901d2915b25bf620f372997ca1f20a14f7cefef5ad6f6f4"}, - {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fa44215bc31675a6380cd896dadb7f2054a7b94cfb87e53e52af844c65406a54"}, - {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:a08b4346350660799d81d4016e748bcb134a9083301d41f9618f64a6077f89f2"}, - {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2fb740482794a72e2e5fec58e4d9b00dcd5a60a8cef68431ff12f2ba0e0d9a7e"}, - {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9007bb1290c79402be6b84bcf9e7a622a073859d61fcee146dc7bc47afe328f3"}, - {file = "cytoolz-0.12.2-cp311-cp311-win32.whl", hash = "sha256:a973f5286758f76824ecf19ae1999f6697371a9121c8f163295d181d19a819d7"}, - {file = "cytoolz-0.12.2-cp311-cp311-win_amd64.whl", hash = "sha256:1ce324d1b413636ea5ee929f79637821f13c9e55e9588f38228947294944d2ed"}, - {file = "cytoolz-0.12.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c08094b9e5d1b6dfb0845a0253cc2655ca64ce70d15162dfdb102e28c8993493"}, - {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baf020f4b708f800b353259cd7575e335a79f1ac912d9dda55b2aa0bf3616e42"}, - {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4416ee86a87180b6a28e7483102c92debc077bec59c67eda8cc63fc52a218ac0"}, - {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6ee222671eed5c5b16a5ad2aea07f0a715b8b199ee534834bc1dd2798f1ade7"}, - {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad92e37be0b106fdbc575a3a669b43b364a5ef334495c9764de4c2d7541f7a99"}, - {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:460c05238fbfe6d848141669d17a751a46c923f9f0c9fd8a3a462ab737623a44"}, - {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9e5075e30be626ef0f9bedf7a15f55ed4d7209e832bc314fdc232dbd61dcbf44"}, - {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:03b58f843f09e73414e82e57f7e8d88f087eaabf8f276b866a40661161da6c51"}, - {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5e4e612b7ecc9596e7c859cd9e0cd085e6d0c576b4f0d917299595eb56bf9c05"}, - {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:08a0e03f287e45eb694998bb55ac1643372199c659affa8319dfbbdec7f7fb3c"}, - {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b029bdd5a8b6c9a7c0e8fdbe4fc25ffaa2e09b77f6f3462314696e3a20511829"}, - {file = "cytoolz-0.12.2-cp36-cp36m-win32.whl", hash = "sha256:18580d060fa637ff01541640ecde6de832a248df02b8fb57e6dd578f189d62c7"}, - {file = "cytoolz-0.12.2-cp36-cp36m-win_amd64.whl", hash = "sha256:97cf514a9f3426228d8daf880f56488330e4b2948a6d183a106921217850d9eb"}, - {file = "cytoolz-0.12.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18a0f838677f9510aef0330c0096778dd6406d21d4ff9504bf79d85235a18460"}, - {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb081b2b02bf4405c804de1ece6f904916838ab0e057f1446e4ac12fac827960"}, - {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57233e1600560ceb719bed759dc78393edd541b9a3e7fefc3079abd83c26a6ea"}, - {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0295289c4510efa41174850e75bc9188f82b72b1b54d0ea57d1781729c2924d5"}, - {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a92aab8dd1d427ac9bc7480cfd3481dbab0ef024558f2f5a47de672d8a5ffaa"}, - {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:51d3495235af09f21aa92a7cdd51504bda640b108b6be834448b774f52852c09"}, - {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f9c690b359f503f18bf1c46a6456370e4f6f3fc4320b8774ae69c4f85ecc6c94"}, - {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:481e3129a76ea01adcc0e7097ccb8dbddab1cfc40b6f0e32c670153512957c0f"}, - {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:55e94124af9c8fbb1df54195cc092688fdad0765641b738970b6f1d5ea72e776"}, - {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5616d386dfbfba7c39e9418ba668c734f6ceaacc0130877e8a100cad11e6838b"}, - {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:732d08228fa8d366fec284f7032cc868d28a99fa81fc71e3adf7ecedbcf33a0f"}, - {file = "cytoolz-0.12.2-cp37-cp37m-win32.whl", hash = "sha256:f039c5373f7b314b151432c73219216857b19ab9cb834f0eb5d880f74fc7851c"}, - {file = "cytoolz-0.12.2-cp37-cp37m-win_amd64.whl", hash = "sha256:246368e983eaee9851b15d7755f82030eab4aa82098d2a34f6bef9c689d33fcc"}, - {file = "cytoolz-0.12.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:81074edf3c74bc9bd250d223408a5df0ff745d1f7a462597536cd26b9390e2d6"}, - {file = "cytoolz-0.12.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:960d85ebaa974ecea4e71fa56d098378fa51fd670ee744614cbb95bf95e28fc7"}, - {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c8d0dff4865da54ae825d43e1721925721b19f3b9aca8e730c2ce73dee2c630"}, - {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0a9d12436fd64937bd2c9609605f527af7f1a8db6e6637639b44121c0fe715d6"}, - {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd461e402e24929d866f05061d2f8337e3a8456e75e21b72c125abff2477c7f7"}, - {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0568d4da0a9ee9f9f5ab318f6501557f1cfe26d18c96c8e0dac7332ae04c6717"}, - {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:101b5bd32badfc8b1f9c7be04ba3ae04fb47f9c8736590666ce9449bff76e0b1"}, - {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8bb624dbaef4661f5e3625c1e39ad98ecceef281d1380e2774d8084ad0810275"}, - {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3e993804e6b04113d61fdb9541b6df2f096ec265a506dad7437517470919c90f"}, - {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ab911033e5937fc221a2c165acce7f66ae5ac9d3e54bec56f3c9c197a96be574"}, - {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6de6a4bdfaee382c2de2a3580b3ae76fce6105da202bbd835e5efbeae6a9c6e"}, - {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9480b4b327be83c4d29cb88bcace761b11f5e30198ffe2287889455c6819e934"}, - {file = "cytoolz-0.12.2-cp38-cp38-win32.whl", hash = "sha256:4180b2785d1278e6abb36a72ac97c92432db53fa2df00ee943d2c15a33627d31"}, - {file = "cytoolz-0.12.2-cp38-cp38-win_amd64.whl", hash = "sha256:d0086ba8d41d73647b13087a3ca9c020f6bfec338335037e8f5172b4c7c8dce5"}, - {file = "cytoolz-0.12.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d29988bde28a90a00367edcf92afa1a2f7ecf43ea3ae383291b7da6d380ccc25"}, - {file = "cytoolz-0.12.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:24c0d71e9ac91f4466b1bd280f7de43aa4d94682daaf34d85d867a9b479b87cc"}, - {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa436abd4ac9ca71859baf5794614e6ec8fa27362f0162baedcc059048da55f7"}, - {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45c7b4eac7571707269ebc2893facdf87e359cd5c7cfbfa9e6bd8b33fb1079c5"}, - {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:294d24edc747ef4e1b28e54365f713becb844e7898113fafbe3e9165dc44aeea"}, - {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:478051e5ef8278b2429864c8d148efcebdc2be948a61c9a44757cd8c816c98f5"}, - {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14108cafb140dd68fdda610c2bbc6a37bf052cd48cfebf487ed44145f7a2b67f"}, - {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5fef7b602ccf8a3c77ab483479ccd7a952a8c5bb1c263156671ba7aaa24d1035"}, - {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9bf51354e15520715f068853e6ab8190e77139940e8b8b633bdb587956a08fb0"}, - {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:388f840fd911d61a96e9e595eaf003f9dc39e847c9060b8e623ab29e556f009b"}, - {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:a67f75cc51a2dc7229a8ac84291e4d61dc5abfc8940befcf37a2836d95873340"}, - {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:63b31345e20afda2ae30dba246955517a4264464d75e071fc2fa641e88c763ec"}, - {file = "cytoolz-0.12.2-cp39-cp39-win32.whl", hash = "sha256:f6e86ac2b45a95f75c6f744147483e0fc9697ce7dfe1726083324c236f873f8b"}, - {file = "cytoolz-0.12.2-cp39-cp39-win_amd64.whl", hash = "sha256:5998f81bf6a2b28a802521efe14d9fc119f74b64e87b62ad1b0e7c3d8366d0c7"}, - {file = "cytoolz-0.12.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:593e89e2518eaf81e96edcc9ef2c5fca666e8fc922b03d5cb7a7b8964dbee336"}, - {file = "cytoolz-0.12.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff451d614ca1d4227db0ffa627fb51df71968cf0d9baf0210528dad10fdbc3ab"}, - {file = "cytoolz-0.12.2-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad9ea4a50d2948738351790047d45f2b1a023facc01bf0361988109b177e8b2f"}, - {file = "cytoolz-0.12.2-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbe038bb78d599b5a29d09c438905defaa615a522bc7e12f8016823179439497"}, - {file = "cytoolz-0.12.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d494befe648c13c98c0f3d56d05489c839c9228a32f58e9777305deb6c2c1cee"}, - {file = "cytoolz-0.12.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c26805b6c8dc8565ed91045c44040bf6c0fe5cb5b390c78cd1d9400d08a6cd39"}, - {file = "cytoolz-0.12.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df4e32badb2ccf1773e1e74020b7e3b8caf9e92f842c6be7d14888ecdefc2c6c"}, - {file = "cytoolz-0.12.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce7889dc3701826d519ede93cdff11940fb5567dbdc165dce0e78047eece02b7"}, - {file = "cytoolz-0.12.2-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c820608e7077416f766b148d75e158e454881961881b657cff808529d261dd24"}, - {file = "cytoolz-0.12.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:698da4fa1f7baeea0607738cb1f9877ed1ba50342b29891b0223221679d6f729"}, - {file = "cytoolz-0.12.2.tar.gz", hash = "sha256:31d4b0455d72d914645f803d917daf4f314d115c70de0578d3820deb8b101f66"}, + {file = "cytoolz-0.12.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bbe58e26c84b163beba0fbeacf6b065feabc8f75c6d3fe305550d33f24a2d346"}, + {file = "cytoolz-0.12.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c51b66ada9bfdb88cf711bf350fcc46f82b83a4683cf2413e633c31a64df6201"}, + {file = "cytoolz-0.12.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e70d9c615e5c9dc10d279d1e32e846085fe1fd6f08d623ddd059a92861f4e3dd"}, + {file = "cytoolz-0.12.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a83f4532707963ae1a5108e51fdfe1278cc8724e3301fee48b9e73e1316de64f"}, + {file = "cytoolz-0.12.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d028044524ee2e815f36210a793c414551b689d4f4eda28f8bbb0883ad78bf5f"}, + {file = "cytoolz-0.12.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c2875bcd1397d0627a09a4f9172fa513185ad302c63758efc15b8eb33cc2a98"}, + {file = "cytoolz-0.12.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:131ff4820e5d64a25d7ad3c3556f2d8aa65c66b3f021b03f8a8e98e4180dd808"}, + {file = "cytoolz-0.12.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:04afa90d9d9d18394c40d9bed48c51433d08b57c042e0e50c8c0f9799735dcbd"}, + {file = "cytoolz-0.12.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:dc1ca9c610425f9854323669a671fc163300b873731584e258975adf50931164"}, + {file = "cytoolz-0.12.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bfa3f8e01bc423a933f2e1c510cbb0632c6787865b5242857cc955cae220d1bf"}, + {file = "cytoolz-0.12.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:f702e295dddef5f8af4a456db93f114539b8dc2a7a9bc4de7c7e41d169aa6ec3"}, + {file = "cytoolz-0.12.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0fbad1fb9bb47e827d00e01992a099b0ba79facf5e5aa453be066033232ac4b5"}, + {file = "cytoolz-0.12.3-cp310-cp310-win32.whl", hash = "sha256:8587c3c3dbe78af90c5025288766ac10dc2240c1e76eb0a93a4e244c265ccefd"}, + {file = "cytoolz-0.12.3-cp310-cp310-win_amd64.whl", hash = "sha256:9e45803d9e75ef90a2f859ef8f7f77614730f4a8ce1b9244375734567299d239"}, + {file = "cytoolz-0.12.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3ac4f2fb38bbc67ff1875b7d2f0f162a247f43bd28eb7c9d15e6175a982e558d"}, + {file = "cytoolz-0.12.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0cf1e1e96dd86829a0539baf514a9c8473a58fbb415f92401a68e8e52a34ecd5"}, + {file = "cytoolz-0.12.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08a438701c6141dd34eaf92e9e9a1f66e23a22f7840ef8a371eba274477de85d"}, + {file = "cytoolz-0.12.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6b6f11b0d7ed91be53166aeef2a23a799e636625675bb30818f47f41ad31821"}, + {file = "cytoolz-0.12.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7fde09384d23048a7b4ac889063761e44b89a0b64015393e2d1d21d5c1f534a"}, + {file = "cytoolz-0.12.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d3bfe45173cc8e6c76206be3a916d8bfd2214fb2965563e288088012f1dabfc"}, + {file = "cytoolz-0.12.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27513a5d5b6624372d63313574381d3217a66e7a2626b056c695179623a5cb1a"}, + {file = "cytoolz-0.12.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d294e5e81ff094fe920fd545052ff30838ea49f9e91227a55ecd9f3ca19774a0"}, + {file = "cytoolz-0.12.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:727b01a2004ddb513496507a695e19b5c0cfebcdfcc68349d3efd92a1c297bf4"}, + {file = "cytoolz-0.12.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:fe1e1779a39dbe83f13886d2b4b02f8c4b10755e3c8d9a89b630395f49f4f406"}, + {file = "cytoolz-0.12.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:de74ef266e2679c3bf8b5fc20cee4fc0271ba13ae0d9097b1491c7a9bcadb389"}, + {file = "cytoolz-0.12.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e04d22049233394e0b08193aca9737200b4a2afa28659d957327aa780ddddf2"}, + {file = "cytoolz-0.12.3-cp311-cp311-win32.whl", hash = "sha256:20d36430d8ac809186736fda735ee7d595b6242bdb35f69b598ef809ebfa5605"}, + {file = "cytoolz-0.12.3-cp311-cp311-win_amd64.whl", hash = "sha256:780c06110f383344d537f48d9010d79fa4f75070d214fc47f389357dd4f010b6"}, + {file = "cytoolz-0.12.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:86923d823bd19ce35805953b018d436f6b862edd6a7c8b747a13d52b39ed5716"}, + {file = "cytoolz-0.12.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a3e61acfd029bfb81c2c596249b508dfd2b4f72e31b7b53b62e5fb0507dd7293"}, + {file = "cytoolz-0.12.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd728f4e6051af6af234651df49319da1d813f47894d4c3c8ab7455e01703a37"}, + {file = "cytoolz-0.12.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fe8c6267caa7ec67bcc37e360f0d8a26bc3bdce510b15b97f2f2e0143bdd3673"}, + {file = "cytoolz-0.12.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99462abd8323c52204a2a0ce62454ce8fa0f4e94b9af397945c12830de73f27e"}, + {file = "cytoolz-0.12.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da125221b1fa25c690fcd030a54344cecec80074df018d906fc6a99f46c1e3a6"}, + {file = "cytoolz-0.12.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c18e351956f70db9e2d04ff02f28e9a41839250d3f936a4c8a1eabd1c3094d2"}, + {file = "cytoolz-0.12.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:921e6d2440ac758c4945c587b1d1d9b781b72737ac0c0ca5d5e02ca1db8bded2"}, + {file = "cytoolz-0.12.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1651a9bd591a8326329ce1d6336f3129161a36d7061a4d5ea9e5377e033364cf"}, + {file = "cytoolz-0.12.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8893223b87c2782bd59f9c4bd5c7bf733edd8728b523c93efb91d7468b486528"}, + {file = "cytoolz-0.12.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:e4d2961644153c5ae186db964aa9f6109da81b12df0f1d3494b4e5cf2c332ee2"}, + {file = "cytoolz-0.12.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:71b6eb97f6695f7ba8ce69c49b707a351c5f46fd97f5aeb5f6f2fb0d6e72b887"}, + {file = "cytoolz-0.12.3-cp312-cp312-win32.whl", hash = "sha256:cee3de65584e915053412cd178729ff510ad5f8f585c21c5890e91028283518f"}, + {file = "cytoolz-0.12.3-cp312-cp312-win_amd64.whl", hash = "sha256:9eef0d23035fa4dcfa21e570961e86c375153a7ee605cdd11a8b088c24f707f6"}, + {file = "cytoolz-0.12.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9a38332cfad2a91e89405b7c18b3f00e2edc951c225accbc217597d3e4e9fde"}, + {file = "cytoolz-0.12.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f501ae1353071fa5d6677437bbeb1aeb5622067dce0977cedc2c5ec5843b202"}, + {file = "cytoolz-0.12.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56f899758146a52e2f8cfb3fb6f4ca19c1e5814178c3d584de35f9e4d7166d91"}, + {file = "cytoolz-0.12.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:800f0526adf9e53d3c6acda748f4def1f048adaa780752f154da5cf22aa488a2"}, + {file = "cytoolz-0.12.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0976a3fcb81d065473173e9005848218ce03ddb2ec7d40dd6a8d2dba7f1c3ae"}, + {file = "cytoolz-0.12.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c835eab01466cb67d0ce6290601ebef2d82d8d0d0a285ed0d6e46989e4a7a71a"}, + {file = "cytoolz-0.12.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4fba0616fcd487e34b8beec1ad9911d192c62e758baa12fcb44448b9b6feae22"}, + {file = "cytoolz-0.12.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6f6e8207d732651e0204779e1ba5a4925c93081834570411f959b80681f8d333"}, + {file = "cytoolz-0.12.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:8119bf5961091cfe644784d0bae214e273b3b3a479f93ee3baab97bbd995ccfe"}, + {file = "cytoolz-0.12.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7ad1331cb68afeec58469c31d944a2100cee14eac221553f0d5218ace1a0b25d"}, + {file = "cytoolz-0.12.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:92c53d508fb8a4463acc85b322fa24734efdc66933a5c8661bdc862103a3373d"}, + {file = "cytoolz-0.12.3-cp37-cp37m-win32.whl", hash = "sha256:2c6dd75dae3d84fa8988861ab8b1189d2488cb8a9b8653828f9cd6126b5e7abd"}, + {file = "cytoolz-0.12.3-cp37-cp37m-win_amd64.whl", hash = "sha256:caf07a97b5220e6334dd32c8b6d8b2bd255ca694eca5dfe914bb5b880ee66cdb"}, + {file = "cytoolz-0.12.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ed0cfb9326747759e2ad81cb6e45f20086a273b67ac3a4c00b19efcbab007c60"}, + {file = "cytoolz-0.12.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:96a5a0292575c3697121f97cc605baf2fd125120c7dcdf39edd1a135798482ca"}, + {file = "cytoolz-0.12.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b76f2f50a789c44d6fd7f773ec43d2a8686781cd52236da03f7f7d7998989bee"}, + {file = "cytoolz-0.12.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2905fdccacc64b4beba37f95cab9d792289c80f4d70830b70de2fc66c007ec01"}, + {file = "cytoolz-0.12.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ebe23028eac51251f22ba01dba6587d30aa9c320372ca0c14eeab67118ec3f"}, + {file = "cytoolz-0.12.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96c715404a3825e37fe3966fe84c5f8a1f036e7640b2a02dbed96cac0c933451"}, + {file = "cytoolz-0.12.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bac0adffc1b6b6a4c5f1fd1dd2161afb720bcc771a91016dc6bdba59af0a5d3"}, + {file = "cytoolz-0.12.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:37441bf4a2a4e2e0fe9c3b0ea5e72db352f5cca03903977ffc42f6f6c5467be9"}, + {file = "cytoolz-0.12.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f04037302049cb30033f7fa4e1d0e44afe35ed6bfcf9b380fc11f2a27d3ed697"}, + {file = "cytoolz-0.12.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f37b60e66378e7a116931d7220f5352186abfcc950d64856038aa2c01944929c"}, + {file = "cytoolz-0.12.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ec9be3e4b6f86ea8b294d34c990c99d2ba6c526ef1e8f46f1d52c263d4f32cd7"}, + {file = "cytoolz-0.12.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0e9199c9e3fbf380a92b8042c677eb9e7ed4bccb126de5e9c0d26f5888d96788"}, + {file = "cytoolz-0.12.3-cp38-cp38-win32.whl", hash = "sha256:18cd61e078bd6bffe088e40f1ed02001387c29174750abce79499d26fa57f5eb"}, + {file = "cytoolz-0.12.3-cp38-cp38-win_amd64.whl", hash = "sha256:765b8381d4003ceb1a07896a854eee2c31ebc950a4ae17d1e7a17c2a8feb2a68"}, + {file = "cytoolz-0.12.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b4a52dd2a36b0a91f7aa50ca6c8509057acc481a24255f6cb07b15d339a34e0f"}, + {file = "cytoolz-0.12.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:581f1ce479769fe7eeb9ae6d87eadb230df8c7c5fff32138162cdd99d7fb8fc3"}, + {file = "cytoolz-0.12.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46f505d4c6eb79585c8ad0b9dc140ef30a138c880e4e3b40230d642690e36366"}, + {file = "cytoolz-0.12.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59276021619b432a5c21c01cda8320b9cc7dbc40351ffc478b440bfccd5bbdd3"}, + {file = "cytoolz-0.12.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e44f4c25e1e7cf6149b499c74945a14649c8866d36371a2c2d2164e4649e7755"}, + {file = "cytoolz-0.12.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c64f8e60c1dd69e4d5e615481f2d57937746f4a6be2d0f86e9e7e3b9e2243b5e"}, + {file = "cytoolz-0.12.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33c63186f3bf9d7ef1347bc0537bb9a0b4111a0d7d6e619623cabc18fef0dc3b"}, + {file = "cytoolz-0.12.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fdddb9d988405f24035234f1e8d1653ab2e48cc2404226d21b49a129aefd1d25"}, + {file = "cytoolz-0.12.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6986632d8a969ea1e720990c818dace1a24c11015fd7c59b9fea0b65ef71f726"}, + {file = "cytoolz-0.12.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0ba1cbc4d9cd7571c917f88f4a069568e5121646eb5d82b2393b2cf84712cf2a"}, + {file = "cytoolz-0.12.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7d267ffc9a36c0a9a58c7e0adc9fa82620f22e4a72533e15dd1361f57fc9accf"}, + {file = "cytoolz-0.12.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95e878868a172a41fbf6c505a4b967309e6870e22adc7b1c3b19653d062711fa"}, + {file = "cytoolz-0.12.3-cp39-cp39-win32.whl", hash = "sha256:8e21932d6d260996f7109f2a40b2586070cb0a0cf1d65781e156326d5ebcc329"}, + {file = "cytoolz-0.12.3-cp39-cp39-win_amd64.whl", hash = "sha256:0d8edfbc694af6c9bda4db56643fb8ed3d14e47bec358c2f1417de9a12d6d1fb"}, + {file = "cytoolz-0.12.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:55f9bd1ae6c2a27eda5abe2a0b65a83029d2385c5a1da7b8ef47af5905d7e905"}, + {file = "cytoolz-0.12.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2d271393c378282727f1231d40391ae93b93ddc0997448acc21dd0cb6a1e56d"}, + {file = "cytoolz-0.12.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee98968d6a66ee83a8ceabf31182189ab5d8598998c8ce69b6d5843daeb2db60"}, + {file = "cytoolz-0.12.3-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01cfb8518828c1189200c02a5010ea404407fb18fd5589e29c126e84bbeadd36"}, + {file = "cytoolz-0.12.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:456395d7aec01db32bf9e6db191d667347c78d8d48e77234521fa1078f60dabb"}, + {file = "cytoolz-0.12.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:cd88028bb897fba99ddd84f253ca6bef73ecb7bdf3f3cf25bc493f8f97d3c7c5"}, + {file = "cytoolz-0.12.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59b19223e7f7bd7a73ec3aa6fdfb73b579ff09c2bc0b7d26857eec2d01a58c76"}, + {file = "cytoolz-0.12.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a79d72b08048a0980a59457c239555f111ac0c8bdc140c91a025f124104dbb4"}, + {file = "cytoolz-0.12.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1dd70141b32b717696a72b8876e86bc9c6f8eff995c1808e299db3541213ff82"}, + {file = "cytoolz-0.12.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:a1445c91009eb775d479e88954c51d0b4cf9a1e8ce3c503c2672d17252882647"}, + {file = "cytoolz-0.12.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ca6a9a9300d5bda417d9090107c6d2b007683efc59d63cc09aca0e7930a08a85"}, + {file = "cytoolz-0.12.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be6feb903d2a08a4ba2e70e950e862fd3be9be9a588b7c38cee4728150a52918"}, + {file = "cytoolz-0.12.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92b6f43f086e5a965d33d62a145ae121b4ccb6e0789ac0acc895ce084fec8c65"}, + {file = "cytoolz-0.12.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:534fa66db8564d9b13872d81d54b6b09ae592c585eb826aac235bd6f1830f8ad"}, + {file = "cytoolz-0.12.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:fea649f979def23150680de1bd1d09682da3b54932800a0f90f29fc2a6c98ba8"}, + {file = "cytoolz-0.12.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a447247ed312dd64e3a8d9483841ecc5338ee26d6e6fbd29cd373ed030db0240"}, + {file = "cytoolz-0.12.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba3f843aa89f35467b38c398ae5b980a824fdbdb94065adc6ec7c47a0a22f4c7"}, + {file = "cytoolz-0.12.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:582c22f97a380211fb36a7b65b1beeb84ea11d82015fa84b054be78580390082"}, + {file = "cytoolz-0.12.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47feb089506fc66e1593cd9ade3945693a9d089a445fbe9a11385cab200b9f22"}, + {file = "cytoolz-0.12.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ba9002d2f043943744a9dc8e50a47362bcb6e6f360dc0a1abcb19642584d87bb"}, + {file = "cytoolz-0.12.3.tar.gz", hash = "sha256:4503dc59f4ced53a54643272c61dc305d1dbbfbd7d6bdf296948de9f34c3a282"}, ] [package.dependencies] @@ -851,23 +832,13 @@ files = [ [[package]] name = "distlib" -version = "0.3.7" +version = "0.3.8" description = "Distribution utilities" optional = false python-versions = "*" files = [ - {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, - {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, -] - -[[package]] -name = "docopt" -version = "0.6.2" -description = "Pythonic argument parser, that will make you smile" -optional = false -python-versions = "*" -files = [ - {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, + {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, + {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, ] [[package]] @@ -890,28 +861,28 @@ gmpy2 = ["gmpy2"] [[package]] name = "eip712" -version = "0.2.2" +version = "0.2.4" description = "eip712: Message classes for typed structured data hashing and signing in Ethereum" optional = false python-versions = ">=3.8,<4" files = [ - {file = "eip712-0.2.2-py3-none-any.whl", hash = "sha256:576476dd1d276e444a633ac22ab25209e18f8f41e5016e576a132d190043a4ba"}, - {file = "eip712-0.2.2.tar.gz", hash = "sha256:6d2e07a83c66fb1cbe2448bb4dfea1c91913c4822b7d9b89231e5b61473ae426"}, + {file = "eip712-0.2.4-py3-none-any.whl", hash = "sha256:19d9abdb4b0ffb97f12a68addc2bbcdb2f0a2da17bc038a22c77b42353de1ecd"}, + {file = "eip712-0.2.4.tar.gz", hash = "sha256:e69760414523f60328279620776549a17ff72f89974688710d3467ae08717070"}, ] [package.dependencies] dataclassy = ">=0.8.2,<1" -eth-abi = ">=4.1.0,<5" -eth-account = ">=0.8.0,<0.9" +eth-abi = ">=4.2.1,<6" +eth-account = ">=0.10.0,<0.11" eth-hash = {version = "*", extras = ["pycryptodome"]} -eth-typing = ">=3.3.0,<4" -eth-utils = ">=2.1.0,<3" +eth-typing = ">=3.5.2,<4" +eth-utils = ">=2.3.1,<3" hexbytes = ">=0.3.0,<1" [package.extras] -dev = ["IPython", "Sphinx (>=5.3.0,<6)", "black (>=23.7.0,<24)", "commitizen (>=2.42,<3)", "flake8 (>=6.0.0,<7)", "hypothesis (>=6.70.0,<7)", "ipdb", "isort (>=5.12.0,<6)", "mdformat (>=0.7.16,<0.8)", "mdformat-frontmatter (>=0.4.1,<0.5)", "mdformat-gfm (>=0.3.5,<0.4)", "mypy (>=1.5.1,<2)", "myst-parser (>=0.18.1,<0.19)", "pre-commit", "pytest (>=6.0,<8)", "pytest-cov", "pytest-watch", "pytest-xdist", "setuptools", "sphinx-rtd-theme (>=1.2.0,<2)", "sphinxcontrib-napoleon (>=0.7)", "twine", "types-setuptools", "wheel"] +dev = ["IPython", "Sphinx (>=5.3.0,<6)", "black (>=23.12.0,<24)", "commitizen (>=2.42,<3)", "flake8 (>=6.1.0,<7)", "hypothesis (>=6.70.0,<7)", "ipdb", "isort (>=5.12.0,<6)", "mdformat (>=0.7.17,<0.8)", "mdformat-frontmatter (>=0.4.1,<0.5)", "mdformat-gfm (>=0.3.5,<0.4)", "mypy (>=1.7.1,<2)", "myst-parser (>=0.18.1,<0.19)", "pre-commit", "pytest (>=6.0,<8)", "pytest-cov", "pytest-watch", "pytest-xdist", "setuptools", "sphinx-rtd-theme (>=1.2.0,<2)", "sphinxcontrib-napoleon (>=0.7)", "twine", "types-setuptools", "wheel"] doc = ["Sphinx (>=5.3.0,<6)", "myst-parser (>=0.18.1,<0.19)", "sphinx-rtd-theme (>=1.2.0,<2)", "sphinxcontrib-napoleon (>=0.7)"] -lint = ["black (>=23.7.0,<24)", "flake8 (>=6.0.0,<7)", "isort (>=5.12.0,<6)", "mdformat (>=0.7.16,<0.8)", "mdformat-frontmatter (>=0.4.1,<0.5)", "mdformat-gfm (>=0.3.5,<0.4)", "mypy (>=1.5.1,<2)", "types-setuptools"] +lint = ["black (>=23.12.0,<24)", "flake8 (>=6.1.0,<7)", "isort (>=5.12.0,<6)", "mdformat (>=0.7.17,<0.8)", "mdformat-frontmatter (>=0.4.1,<0.5)", "mdformat-gfm (>=0.3.5,<0.4)", "mypy (>=1.7.1,<2)", "types-setuptools"] release = ["setuptools", "twine", "wheel"] test = ["hypothesis (>=6.70.0,<7)", "pytest (>=6.0,<8)", "pytest-cov", "pytest-xdist"] @@ -928,13 +899,13 @@ files = [ [[package]] name = "eth-abi" -version = "4.2.1" +version = "5.0.0" description = "eth_abi: Python utilities for working with Ethereum ABI definitions, especially encoding and decoding" optional = false -python-versions = ">=3.7.2, <4" +python-versions = ">=3.8, <4" files = [ - {file = "eth_abi-4.2.1-py3-none-any.whl", hash = "sha256:abd83410a5326145bf178675c276de0ed154f6dc695dcad1beafaa44d97f44ae"}, - {file = "eth_abi-4.2.1.tar.gz", hash = "sha256:60d88788d53725794cdb07c0f0bb0df2a31a6e1ad19644313fe6117ac24eeeb0"}, + {file = "eth_abi-5.0.0-py3-none-any.whl", hash = "sha256:936a715d7366ac13cac665cbdaf01cc4aabbe8c2d810d716287a9634f9665e01"}, + {file = "eth_abi-5.0.0.tar.gz", hash = "sha256:89c4454d794d9ed92ad5cb2794698c5cee6b7b3ca6009187d0e282adc7f9b6dc"}, ] [package.dependencies] @@ -943,126 +914,122 @@ eth-utils = ">=2.0.0" parsimonious = ">=0.9.0,<0.10.0" [package.extras] -dev = ["black (>=23)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "hypothesis (>=4.18.2,<5.0.0)", "ipython", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -doc = ["sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -lint = ["black (>=23)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)"] +dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] test = ["eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-xdist (>=2.4.0)"] tools = ["hypothesis (>=4.18.2,<5.0.0)"] [[package]] name = "eth-account" -version = "0.8.0" +version = "0.10.0" description = "eth-account: Sign Ethereum transactions and messages with local private keys" optional = false -python-versions = ">=3.6, <4" +python-versions = ">=3.7, <4" files = [ - {file = "eth-account-0.8.0.tar.gz", hash = "sha256:ccb2d90a16c81c8ea4ca4dc76a70b50f1d63cea6aff3c5a5eddedf9e45143eca"}, - {file = "eth_account-0.8.0-py3-none-any.whl", hash = "sha256:0ccc0edbb17021004356ae6e37887528b6e59e6ae6283f3917b9759a5887203b"}, + {file = "eth-account-0.10.0.tar.gz", hash = "sha256:474a2fccf7286230cf66502565f03b536921d7e1fdfceba198e42160e5ac4bc1"}, + {file = "eth_account-0.10.0-py3-none-any.whl", hash = "sha256:b7a83f506a8edf57926569e5f04471ce3f1700e572d3421b4ad0dad7a26c0978"}, ] [package.dependencies] -bitarray = ">=2.4.0,<3" -eth-abi = ">=3.0.1" -eth-keyfile = ">=0.6.0,<0.7.0" -eth-keys = ">=0.4.0,<0.5" -eth-rlp = ">=0.3.0,<1" -eth-utils = ">=2.0.0,<3" -hexbytes = ">=0.1.0,<1" -rlp = ">=1.0.0,<4" +bitarray = ">=2.4.0" +eth-abi = ">=4.0.0-b.2" +eth-keyfile = ">=0.6.0" +eth-keys = ">=0.4.0" +eth-rlp = ">=0.3.0" +eth-utils = ">=2.0.0" +hexbytes = ">=0.1.0,<0.4.0" +rlp = ">=1.0.0" [package.extras] -dev = ["Sphinx (>=1.6.5,<5)", "black (>=22,<23)", "bumpversion (>=0.5.3,<1)", "coverage", "flake8 (==3.7.9)", "hypothesis (>=4.18.0,<5)", "ipython", "isort (>=4.2.15,<5)", "jinja2 (>=3.0.0,<3.1.0)", "mypy (==0.910)", "pydocstyle (>=5.0.0,<6)", "pytest (>=6.2.5,<7)", "pytest-watch (>=4.1.0,<5)", "pytest-xdist", "sphinx-rtd-theme (>=0.1.9,<1)", "towncrier (>=21,<22)", "tox (==3.25.0)", "twine", "wheel"] -doc = ["Sphinx (>=1.6.5,<5)", "jinja2 (>=3.0.0,<3.1.0)", "sphinx-rtd-theme (>=0.1.9,<1)", "towncrier (>=21,<22)"] -lint = ["black (>=22,<23)", "flake8 (==3.7.9)", "isort (>=4.2.15,<5)", "mypy (==0.910)", "pydocstyle (>=5.0.0,<6)"] -test = ["coverage", "hypothesis (>=4.18.0,<5)", "pytest (>=6.2.5,<7)", "pytest-xdist", "tox (==3.25.0)"] +dev = ["black (>=23)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "coverage", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "hypothesis (>=4.18.0,<5)", "ipython", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)", "pytest (>=7.0.0)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +doc = ["sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] +lint = ["black (>=23)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)"] +test = ["coverage", "hypothesis (>=4.18.0,<5)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-hash" -version = "0.5.2" +version = "0.6.0" description = "eth-hash: The Ethereum hashing function, keccak256, sometimes (erroneously) called sha3" optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.8, <4" files = [ - {file = "eth-hash-0.5.2.tar.gz", hash = "sha256:1b5f10eca7765cc385e1430eefc5ced6e2e463bb18d1365510e2e539c1a6fe4e"}, - {file = "eth_hash-0.5.2-py3-none-any.whl", hash = "sha256:251f62f6579a1e247561679d78df37548bd5f59908da0b159982bf8293ad32f0"}, + {file = "eth-hash-0.6.0.tar.gz", hash = "sha256:ae72889e60db6acbb3872c288cfa02ed157f4c27630fcd7f9c8442302c31e478"}, + {file = "eth_hash-0.6.0-py3-none-any.whl", hash = "sha256:9f8daaa345764f8871dc461855049ac54ae4291d780279bce6fce7f24e3f17d3"}, ] [package.dependencies] pycryptodome = {version = ">=3.6.6,<4", optional = true, markers = "extra == \"pycryptodome\""} [package.extras] -dev = ["black (>=23)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "ipython", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)", "pytest (>=7.0.0)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -doc = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -lint = ["black (>=23)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)"] +dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] pycryptodome = ["pycryptodome (>=3.6.6,<4)"] pysha3 = ["pysha3 (>=1.0.0,<2.0.0)", "safe-pysha3 (>=1.0.0)"] test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-keyfile" -version = "0.6.1" -description = "A library for handling the encrypted keyfiles used to store ethereum private keys." +version = "0.7.0" +description = "eth-keyfile: A library for handling the encrypted keyfiles used to store ethereum private keys" optional = false -python-versions = "*" +python-versions = ">=3.8, <4" files = [ - {file = "eth-keyfile-0.6.1.tar.gz", hash = "sha256:471be6e5386fce7b22556b3d4bde5558dbce46d2674f00848027cb0a20abdc8c"}, - {file = "eth_keyfile-0.6.1-py3-none-any.whl", hash = "sha256:609773a1ad5956944a33348413cad366ec6986c53357a806528c8f61c4961560"}, + {file = "eth-keyfile-0.7.0.tar.gz", hash = "sha256:6bdb8110c3a50439deb68a04c93c9d5ddd5402353bfae1bf4cfca1d6dff14fcf"}, + {file = "eth_keyfile-0.7.0-py3-none-any.whl", hash = "sha256:6a89b231a2fe250c3a8f924f2695bb9cce33ddd0d6f7ebbcdacd183d7f83d537"}, ] [package.dependencies] -eth-keys = ">=0.4.0,<0.5.0" -eth-utils = ">=2,<3" +eth-keys = ">=0.4.0" +eth-utils = ">=2" pycryptodome = ">=3.6.6,<4" [package.extras] -dev = ["bumpversion (>=0.5.3,<1)", "eth-keys (>=0.4.0,<0.5.0)", "eth-utils (>=2,<3)", "flake8 (==4.0.1)", "idna (==2.7)", "pluggy (>=1.0.0,<2)", "pycryptodome (>=3.6.6,<4)", "pytest (>=6.2.5,<7)", "requests (>=2.20,<3)", "setuptools (>=38.6.0)", "tox (>=2.7.0)", "twine", "wheel"] -keyfile = ["eth-keys (>=0.4.0,<0.5.0)", "eth-utils (>=2,<3)", "pycryptodome (>=3.6.6,<4)"] -lint = ["flake8 (==4.0.1)"] -test = ["pytest (>=6.2.5,<7)"] +dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["towncrier (>=21,<22)"] +test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-keys" -version = "0.4.0" -description = "Common API for Ethereum key operations." +version = "0.5.0" +description = "eth-keys: Common API for Ethereum key operations" optional = false -python-versions = "*" +python-versions = ">=3.8, <4" files = [ - {file = "eth-keys-0.4.0.tar.gz", hash = "sha256:7d18887483bc9b8a3fdd8e32ddcb30044b9f08fcb24a380d93b6eee3a5bb3216"}, - {file = "eth_keys-0.4.0-py3-none-any.whl", hash = "sha256:e07915ffb91277803a28a379418bdd1fad1f390c38ad9353a0f189789a440d5d"}, + {file = "eth-keys-0.5.0.tar.gz", hash = "sha256:a0abccb83f3d84322591a2c047a1e3aa52ea86b185fa3e82ce311d120ca2791e"}, + {file = "eth_keys-0.5.0-py3-none-any.whl", hash = "sha256:b2bed3ff3bcede68cc0cd4458c7147baaeaac1211a1efdb6ca019f9d3d989f2b"}, ] [package.dependencies] -eth-typing = ">=3.0.0,<4" -eth-utils = ">=2.0.0,<3.0.0" +eth-typing = ">=3" +eth-utils = ">=2" [package.extras] -coincurve = ["coincurve (>=7.0.0,<16.0.0)"] -dev = ["asn1tools (>=0.146.2,<0.147)", "bumpversion (==0.5.3)", "eth-hash[pycryptodome]", "eth-hash[pysha3]", "eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)", "factory-boy (>=3.0.1,<3.1)", "flake8 (==3.0.4)", "hypothesis (>=5.10.3,<6.0.0)", "mypy (==0.782)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)", "tox (==3.20.0)", "twine"] -eth-keys = ["eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)"] -lint = ["flake8 (==3.0.4)", "mypy (==0.782)"] -test = ["asn1tools (>=0.146.2,<0.147)", "eth-hash[pycryptodome]", "eth-hash[pysha3]", "factory-boy (>=3.0.1,<3.1)", "hypothesis (>=5.10.3,<6.0.0)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)"] +coincurve = ["coincurve (>=12.0.0)"] +dev = ["asn1tools (>=0.146.2)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "coincurve (>=12.0.0)", "eth-hash[pysha3]", "factory-boy (>=3.0.1)", "hypothesis (>=5.10.3,<6)", "ipython", "pre-commit (>=3.4.0)", "pyasn1 (>=0.4.5)", "pytest (>=7.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["towncrier (>=21,<22)"] +test = ["asn1tools (>=0.146.2)", "eth-hash[pysha3]", "factory-boy (>=3.0.1)", "hypothesis (>=5.10.3,<6)", "pyasn1 (>=0.4.5)", "pytest (>=7.0.0)"] [[package]] name = "eth-rlp" -version = "0.3.0" +version = "1.0.1" description = "eth-rlp: RLP definitions for common Ethereum objects in Python" optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.8, <4" files = [ - {file = "eth-rlp-0.3.0.tar.gz", hash = "sha256:f3263b548df718855d9a8dbd754473f383c0efc82914b0b849572ce3e06e71a6"}, - {file = "eth_rlp-0.3.0-py3-none-any.whl", hash = "sha256:e88e949a533def85c69fa94224618bbbd6de00061f4cff645c44621dab11cf33"}, + {file = "eth-rlp-1.0.1.tar.gz", hash = "sha256:d61dbda892ee1220f28fb3663c08f6383c305db9f1f5624dc585c9cd05115027"}, + {file = "eth_rlp-1.0.1-py3-none-any.whl", hash = "sha256:dd76515d71654277377d48876b88e839d61553aaf56952e580bb7cebef2b1517"}, ] [package.dependencies] -eth-utils = ">=2.0.0,<3" +eth-utils = ">=2.0.0" hexbytes = ">=0.1.0,<1" -rlp = ">=0.6.0,<4" +rlp = ">=0.6.0" +typing-extensions = {version = ">=4.0.1", markers = "python_version <= \"3.11\""} [package.extras] -dev = ["Sphinx (>=1.6.5,<2)", "bumpversion (>=0.5.3,<1)", "eth-hash[pycryptodome]", "flake8 (==3.7.9)", "ipython", "isort (>=4.2.15,<5)", "mypy (==0.770)", "pydocstyle (>=3.0.0,<4)", "pytest (>=6.2.5,<7)", "pytest-watch (>=4.1.0,<5)", "pytest-xdist", "sphinx-rtd-theme (>=0.1.9)", "towncrier (>=19.2.0,<20)", "tox (==3.14.6)", "twine", "wheel"] -doc = ["Sphinx (>=1.6.5,<2)", "sphinx-rtd-theme (>=0.1.9)", "towncrier (>=19.2.0,<20)"] -lint = ["flake8 (==3.7.9)", "isort (>=4.2.15,<5)", "mypy (==0.770)", "pydocstyle (>=3.0.0,<4)"] -test = ["eth-hash[pycryptodome]", "pytest (>=6.2.5,<7)", "pytest-xdist", "tox (==3.14.6)"] +dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] +test = ["eth-hash[pycryptodome]", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-typing" @@ -1177,205 +1144,221 @@ docs = ["alabaster", "myst-parser (>=0.18.0,<0.19.0)", "pygments-github-lexers", [[package]] name = "frozenlist" -version = "1.4.0" +version = "1.4.1" description = "A list-like structure which implements collections.abc.MutableSequence" optional = false python-versions = ">=3.8" files = [ - {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"}, - {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"}, - {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"}, - {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"}, - {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"}, - {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"}, - {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"}, - {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"}, - {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"}, - {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"}, - {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"}, - {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, + {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, + {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, + {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, + {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, + {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, + {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, + {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, + {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, + {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, + {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, + {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, + {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, ] [[package]] name = "grpcio" -version = "1.60.0" +version = "1.60.1" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.7" files = [ - {file = "grpcio-1.60.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:d020cfa595d1f8f5c6b343530cd3ca16ae5aefdd1e832b777f9f0eb105f5b139"}, - {file = "grpcio-1.60.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:b98f43fcdb16172dec5f4b49f2fece4b16a99fd284d81c6bbac1b3b69fcbe0ff"}, - {file = "grpcio-1.60.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:20e7a4f7ded59097c84059d28230907cd97130fa74f4a8bfd1d8e5ba18c81491"}, - {file = "grpcio-1.60.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:452ca5b4afed30e7274445dd9b441a35ece656ec1600b77fff8c216fdf07df43"}, - {file = "grpcio-1.60.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43e636dc2ce9ece583b3e2ca41df5c983f4302eabc6d5f9cd04f0562ee8ec1ae"}, - {file = "grpcio-1.60.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e306b97966369b889985a562ede9d99180def39ad42c8014628dd3cc343f508"}, - {file = "grpcio-1.60.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f897c3b127532e6befdcf961c415c97f320d45614daf84deba0a54e64ea2457b"}, - {file = "grpcio-1.60.0-cp310-cp310-win32.whl", hash = "sha256:b87efe4a380887425bb15f220079aa8336276398dc33fce38c64d278164f963d"}, - {file = "grpcio-1.60.0-cp310-cp310-win_amd64.whl", hash = "sha256:a9c7b71211f066908e518a2ef7a5e211670761651039f0d6a80d8d40054047df"}, - {file = "grpcio-1.60.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:fb464479934778d7cc5baf463d959d361954d6533ad34c3a4f1d267e86ee25fd"}, - {file = "grpcio-1.60.0-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:4b44d7e39964e808b071714666a812049765b26b3ea48c4434a3b317bac82f14"}, - {file = "grpcio-1.60.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:90bdd76b3f04bdb21de5398b8a7c629676c81dfac290f5f19883857e9371d28c"}, - {file = "grpcio-1.60.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91229d7203f1ef0ab420c9b53fe2ca5c1fbeb34f69b3bc1b5089466237a4a134"}, - {file = "grpcio-1.60.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b36a2c6d4920ba88fa98075fdd58ff94ebeb8acc1215ae07d01a418af4c0253"}, - {file = "grpcio-1.60.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:297eef542156d6b15174a1231c2493ea9ea54af8d016b8ca7d5d9cc65cfcc444"}, - {file = "grpcio-1.60.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:87c9224acba0ad8bacddf427a1c2772e17ce50b3042a789547af27099c5f751d"}, - {file = "grpcio-1.60.0-cp311-cp311-win32.whl", hash = "sha256:95ae3e8e2c1b9bf671817f86f155c5da7d49a2289c5cf27a319458c3e025c320"}, - {file = "grpcio-1.60.0-cp311-cp311-win_amd64.whl", hash = "sha256:467a7d31554892eed2aa6c2d47ded1079fc40ea0b9601d9f79204afa8902274b"}, - {file = "grpcio-1.60.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:a7152fa6e597c20cb97923407cf0934e14224af42c2b8d915f48bc3ad2d9ac18"}, - {file = "grpcio-1.60.0-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:7db16dd4ea1b05ada504f08d0dca1cd9b926bed3770f50e715d087c6f00ad748"}, - {file = "grpcio-1.60.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:b0571a5aef36ba9177e262dc88a9240c866d903a62799e44fd4aae3f9a2ec17e"}, - {file = "grpcio-1.60.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fd9584bf1bccdfff1512719316efa77be235469e1e3295dce64538c4773840b"}, - {file = "grpcio-1.60.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6a478581b1a1a8fdf3318ecb5f4d0cda41cacdffe2b527c23707c9c1b8fdb55"}, - {file = "grpcio-1.60.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:77c8a317f0fd5a0a2be8ed5cbe5341537d5c00bb79b3bb27ba7c5378ba77dbca"}, - {file = "grpcio-1.60.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1c30bb23a41df95109db130a6cc1b974844300ae2e5d68dd4947aacba5985aa5"}, - {file = "grpcio-1.60.0-cp312-cp312-win32.whl", hash = "sha256:2aef56e85901c2397bd557c5ba514f84de1f0ae5dd132f5d5fed042858115951"}, - {file = "grpcio-1.60.0-cp312-cp312-win_amd64.whl", hash = "sha256:e381fe0c2aa6c03b056ad8f52f8efca7be29fb4d9ae2f8873520843b6039612a"}, - {file = "grpcio-1.60.0-cp37-cp37m-linux_armv7l.whl", hash = "sha256:92f88ca1b956eb8427a11bb8b4a0c0b2b03377235fc5102cb05e533b8693a415"}, - {file = "grpcio-1.60.0-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:e278eafb406f7e1b1b637c2cf51d3ad45883bb5bd1ca56bc05e4fc135dfdaa65"}, - {file = "grpcio-1.60.0-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:a48edde788b99214613e440fce495bbe2b1e142a7f214cce9e0832146c41e324"}, - {file = "grpcio-1.60.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de2ad69c9a094bf37c1102b5744c9aec6cf74d2b635558b779085d0263166454"}, - {file = "grpcio-1.60.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:073f959c6f570797272f4ee9464a9997eaf1e98c27cb680225b82b53390d61e6"}, - {file = "grpcio-1.60.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c826f93050c73e7769806f92e601e0efdb83ec8d7c76ddf45d514fee54e8e619"}, - {file = "grpcio-1.60.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9e30be89a75ee66aec7f9e60086fadb37ff8c0ba49a022887c28c134341f7179"}, - {file = "grpcio-1.60.0-cp37-cp37m-win_amd64.whl", hash = "sha256:b0fb2d4801546598ac5cd18e3ec79c1a9af8b8f2a86283c55a5337c5aeca4b1b"}, - {file = "grpcio-1.60.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:9073513ec380434eb8d21970e1ab3161041de121f4018bbed3146839451a6d8e"}, - {file = "grpcio-1.60.0-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:74d7d9fa97809c5b892449b28a65ec2bfa458a4735ddad46074f9f7d9550ad13"}, - {file = "grpcio-1.60.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:1434ca77d6fed4ea312901122dc8da6c4389738bf5788f43efb19a838ac03ead"}, - {file = "grpcio-1.60.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e61e76020e0c332a98290323ecfec721c9544f5b739fab925b6e8cbe1944cf19"}, - {file = "grpcio-1.60.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675997222f2e2f22928fbba640824aebd43791116034f62006e19730715166c0"}, - {file = "grpcio-1.60.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5208a57eae445ae84a219dfd8b56e04313445d146873117b5fa75f3245bc1390"}, - {file = "grpcio-1.60.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:428d699c8553c27e98f4d29fdc0f0edc50e9a8a7590bfd294d2edb0da7be3629"}, - {file = "grpcio-1.60.0-cp38-cp38-win32.whl", hash = "sha256:83f2292ae292ed5a47cdcb9821039ca8e88902923198f2193f13959360c01860"}, - {file = "grpcio-1.60.0-cp38-cp38-win_amd64.whl", hash = "sha256:705a68a973c4c76db5d369ed573fec3367d7d196673fa86614b33d8c8e9ebb08"}, - {file = "grpcio-1.60.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:c193109ca4070cdcaa6eff00fdb5a56233dc7610216d58fb81638f89f02e4968"}, - {file = "grpcio-1.60.0-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:676e4a44e740deaba0f4d95ba1d8c5c89a2fcc43d02c39f69450b1fa19d39590"}, - {file = "grpcio-1.60.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:5ff21e000ff2f658430bde5288cb1ac440ff15c0d7d18b5fb222f941b46cb0d2"}, - {file = "grpcio-1.60.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c86343cf9ff7b2514dd229bdd88ebba760bd8973dac192ae687ff75e39ebfab"}, - {file = "grpcio-1.60.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fd3b3968ffe7643144580f260f04d39d869fcc2cddb745deef078b09fd2b328"}, - {file = "grpcio-1.60.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:30943b9530fe3620e3b195c03130396cd0ee3a0d10a66c1bee715d1819001eaf"}, - {file = "grpcio-1.60.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b10241250cb77657ab315270b064a6c7f1add58af94befa20687e7c8d8603ae6"}, - {file = "grpcio-1.60.0-cp39-cp39-win32.whl", hash = "sha256:79a050889eb8d57a93ed21d9585bb63fca881666fc709f5d9f7f9372f5e7fd03"}, - {file = "grpcio-1.60.0-cp39-cp39-win_amd64.whl", hash = "sha256:8a97a681e82bc11a42d4372fe57898d270a2707f36c45c6676e49ce0d5c41353"}, - {file = "grpcio-1.60.0.tar.gz", hash = "sha256:2199165a1affb666aa24adf0c97436686d0a61bc5fc113c037701fb7c7fceb96"}, + {file = "grpcio-1.60.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:14e8f2c84c0832773fb3958240c69def72357bc11392571f87b2d7b91e0bb092"}, + {file = "grpcio-1.60.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:33aed0a431f5befeffd9d346b0fa44b2c01aa4aeae5ea5b2c03d3e25e0071216"}, + {file = "grpcio-1.60.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:fead980fbc68512dfd4e0c7b1f5754c2a8e5015a04dea454b9cada54a8423525"}, + {file = "grpcio-1.60.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:082081e6a36b6eb5cf0fd9a897fe777dbb3802176ffd08e3ec6567edd85bc104"}, + {file = "grpcio-1.60.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55ccb7db5a665079d68b5c7c86359ebd5ebf31a19bc1a91c982fd622f1e31ff2"}, + {file = "grpcio-1.60.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9b54577032d4f235452f77a83169b6527bf4b77d73aeada97d45b2aaf1bf5ce0"}, + {file = "grpcio-1.60.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7d142bcd604166417929b071cd396aa13c565749a4c840d6c702727a59d835eb"}, + {file = "grpcio-1.60.1-cp310-cp310-win32.whl", hash = "sha256:2a6087f234cb570008a6041c8ffd1b7d657b397fdd6d26e83d72283dae3527b1"}, + {file = "grpcio-1.60.1-cp310-cp310-win_amd64.whl", hash = "sha256:f2212796593ad1d0235068c79836861f2201fc7137a99aa2fea7beeb3b101177"}, + {file = "grpcio-1.60.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:79ae0dc785504cb1e1788758c588c711f4e4a0195d70dff53db203c95a0bd303"}, + {file = "grpcio-1.60.1-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:4eec8b8c1c2c9b7125508ff7c89d5701bf933c99d3910e446ed531cd16ad5d87"}, + {file = "grpcio-1.60.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:8c9554ca8e26241dabe7951aa1fa03a1ba0856688ecd7e7bdbdd286ebc272e4c"}, + {file = "grpcio-1.60.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91422ba785a8e7a18725b1dc40fbd88f08a5bb4c7f1b3e8739cab24b04fa8a03"}, + {file = "grpcio-1.60.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cba6209c96828711cb7c8fcb45ecef8c8859238baf15119daa1bef0f6c84bfe7"}, + {file = "grpcio-1.60.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c71be3f86d67d8d1311c6076a4ba3b75ba5703c0b856b4e691c9097f9b1e8bd2"}, + {file = "grpcio-1.60.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:af5ef6cfaf0d023c00002ba25d0751e5995fa0e4c9eec6cd263c30352662cbce"}, + {file = "grpcio-1.60.1-cp311-cp311-win32.whl", hash = "sha256:a09506eb48fa5493c58f946c46754ef22f3ec0df64f2b5149373ff31fb67f3dd"}, + {file = "grpcio-1.60.1-cp311-cp311-win_amd64.whl", hash = "sha256:49c9b6a510e3ed8df5f6f4f3c34d7fbf2d2cae048ee90a45cd7415abab72912c"}, + {file = "grpcio-1.60.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:b58b855d0071575ea9c7bc0d84a06d2edfbfccec52e9657864386381a7ce1ae9"}, + {file = "grpcio-1.60.1-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:a731ac5cffc34dac62053e0da90f0c0b8560396a19f69d9703e88240c8f05858"}, + {file = "grpcio-1.60.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:cf77f8cf2a651fbd869fbdcb4a1931464189cd210abc4cfad357f1cacc8642a6"}, + {file = "grpcio-1.60.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c557e94e91a983e5b1e9c60076a8fd79fea1e7e06848eb2e48d0ccfb30f6e073"}, + {file = "grpcio-1.60.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:069fe2aeee02dfd2135d562d0663fe70fbb69d5eed6eb3389042a7e963b54de8"}, + {file = "grpcio-1.60.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cb0af13433dbbd1c806e671d81ec75bd324af6ef75171fd7815ca3074fe32bfe"}, + {file = "grpcio-1.60.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2f44c32aef186bbba254129cea1df08a20be414144ac3bdf0e84b24e3f3b2e05"}, + {file = "grpcio-1.60.1-cp312-cp312-win32.whl", hash = "sha256:a212e5dea1a4182e40cd3e4067ee46be9d10418092ce3627475e995cca95de21"}, + {file = "grpcio-1.60.1-cp312-cp312-win_amd64.whl", hash = "sha256:6e490fa5f7f5326222cb9f0b78f207a2b218a14edf39602e083d5f617354306f"}, + {file = "grpcio-1.60.1-cp37-cp37m-linux_armv7l.whl", hash = "sha256:4216e67ad9a4769117433814956031cb300f85edc855252a645a9a724b3b6594"}, + {file = "grpcio-1.60.1-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:73e14acd3d4247169955fae8fb103a2b900cfad21d0c35f0dcd0fdd54cd60367"}, + {file = "grpcio-1.60.1-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:6ecf21d20d02d1733e9c820fb5c114c749d888704a7ec824b545c12e78734d1c"}, + {file = "grpcio-1.60.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33bdea30dcfd4f87b045d404388469eb48a48c33a6195a043d116ed1b9a0196c"}, + {file = "grpcio-1.60.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53b69e79d00f78c81eecfb38f4516080dc7f36a198b6b37b928f1c13b3c063e9"}, + {file = "grpcio-1.60.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:39aa848794b887120b1d35b1b994e445cc028ff602ef267f87c38122c1add50d"}, + {file = "grpcio-1.60.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:72153a0d2e425f45b884540a61c6639436ddafa1829a42056aa5764b84108b8e"}, + {file = "grpcio-1.60.1-cp37-cp37m-win_amd64.whl", hash = "sha256:50d56280b482875d1f9128ce596e59031a226a8b84bec88cb2bf76c289f5d0de"}, + {file = "grpcio-1.60.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:6d140bdeb26cad8b93c1455fa00573c05592793c32053d6e0016ce05ba267549"}, + {file = "grpcio-1.60.1-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:bc808924470643b82b14fe121923c30ec211d8c693e747eba8a7414bc4351a23"}, + {file = "grpcio-1.60.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:70c83bb530572917be20c21f3b6be92cd86b9aecb44b0c18b1d3b2cc3ae47df0"}, + {file = "grpcio-1.60.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9b106bc52e7f28170e624ba61cc7dc6829566e535a6ec68528f8e1afbed1c41f"}, + {file = "grpcio-1.60.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30e980cd6db1088c144b92fe376747328d5554bc7960ce583ec7b7d81cd47287"}, + {file = "grpcio-1.60.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0c5807e9152eff15f1d48f6b9ad3749196f79a4a050469d99eecb679be592acc"}, + {file = "grpcio-1.60.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f1c3dc536b3ee124e8b24feb7533e5c70b9f2ef833e3b2e5513b2897fd46763a"}, + {file = "grpcio-1.60.1-cp38-cp38-win32.whl", hash = "sha256:d7404cebcdb11bb5bd40bf94131faf7e9a7c10a6c60358580fe83913f360f929"}, + {file = "grpcio-1.60.1-cp38-cp38-win_amd64.whl", hash = "sha256:c8754c75f55781515a3005063d9a05878b2cfb3cb7e41d5401ad0cf19de14872"}, + {file = "grpcio-1.60.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:0250a7a70b14000fa311de04b169cc7480be6c1a769b190769d347939d3232a8"}, + {file = "grpcio-1.60.1-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:660fc6b9c2a9ea3bb2a7e64ba878c98339abaf1811edca904ac85e9e662f1d73"}, + {file = "grpcio-1.60.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:76eaaba891083fcbe167aa0f03363311a9f12da975b025d30e94b93ac7a765fc"}, + {file = "grpcio-1.60.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d97c65ea7e097056f3d1ead77040ebc236feaf7f71489383d20f3b4c28412a"}, + {file = "grpcio-1.60.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb2a2911b028f01c8c64d126f6b632fcd8a9ac975aa1b3855766c94e4107180"}, + {file = "grpcio-1.60.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:5a1ebbae7e2214f51b1f23b57bf98eeed2cf1ba84e4d523c48c36d5b2f8829ff"}, + {file = "grpcio-1.60.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a66f4d2a005bc78e61d805ed95dedfcb35efa84b7bba0403c6d60d13a3de2d6"}, + {file = "grpcio-1.60.1-cp39-cp39-win32.whl", hash = "sha256:8d488fbdbf04283f0d20742b64968d44825617aa6717b07c006168ed16488804"}, + {file = "grpcio-1.60.1-cp39-cp39-win_amd64.whl", hash = "sha256:61b7199cd2a55e62e45bfb629a35b71fc2c0cb88f686a047f25b1112d3810904"}, + {file = "grpcio-1.60.1.tar.gz", hash = "sha256:dd1d3a8d1d2e50ad9b59e10aa7f07c7d1be2b367f3f2d33c5fade96ed5460962"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.60.0)"] +protobuf = ["grpcio-tools (>=1.60.1)"] [[package]] name = "grpcio-tools" -version = "1.60.0" +version = "1.60.1" description = "Protobuf code generator for gRPC" optional = false python-versions = ">=3.7" files = [ - {file = "grpcio-tools-1.60.0.tar.gz", hash = "sha256:ed30499340228d733ff69fcf4a66590ed7921f94eb5a2bf692258b1280b9dac7"}, - {file = "grpcio_tools-1.60.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:6807b7a3f3e6e594566100bd7fe04a2c42ce6d5792652677f1aaf5aa5adaef3d"}, - {file = "grpcio_tools-1.60.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:857c5351e9dc33a019700e171163f94fcc7e3ae0f6d2b026b10fda1e3c008ef1"}, - {file = "grpcio_tools-1.60.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:ec0e401e9a43d927d216d5169b03c61163fb52b665c5af2fed851357b15aef88"}, - {file = "grpcio_tools-1.60.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e68dc4474f30cad11a965f0eb5d37720a032b4720afa0ec19dbcea2de73b5aae"}, - {file = "grpcio_tools-1.60.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbf0ed772d2ae7e8e5d7281fcc00123923ab130b94f7a843eee9af405918f924"}, - {file = "grpcio_tools-1.60.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c771b19dce2bfe06899247168c077d7ab4e273f6655d8174834f9a6034415096"}, - {file = "grpcio_tools-1.60.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e5614cf0960456d21d8a0f4902e3e5e3bcacc4e400bf22f196e5dd8aabb978b7"}, - {file = "grpcio_tools-1.60.0-cp310-cp310-win32.whl", hash = "sha256:87cf439178f3eb45c1a889b2e4a17cbb4c450230d92c18d9c57e11271e239c55"}, - {file = "grpcio_tools-1.60.0-cp310-cp310-win_amd64.whl", hash = "sha256:687f576d7ff6ce483bc9a196d1ceac45144e8733b953620a026daed8e450bc38"}, - {file = "grpcio_tools-1.60.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2a8a758701f3ac07ed85f5a4284c6a9ddefcab7913a8e552497f919349e72438"}, - {file = "grpcio_tools-1.60.0-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:7c1cde49631732356cb916ee1710507967f19913565ed5f9991e6c9cb37e3887"}, - {file = "grpcio_tools-1.60.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:d941749bd8dc3f8be58fe37183143412a27bec3df8482d5abd6b4ec3f1ac2924"}, - {file = "grpcio_tools-1.60.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ee35234f1da8fba7ddbc544856ff588243f1128ea778d7a1da3039be829a134"}, - {file = "grpcio_tools-1.60.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8f7a5094adb49e85db13ea3df5d99a976c2bdfd83b0ba26af20ebb742ac6786"}, - {file = "grpcio_tools-1.60.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:24c4ead4a03037beaeb8ef2c90d13d70101e35c9fae057337ed1a9144ef10b53"}, - {file = "grpcio_tools-1.60.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:811abb9c4fb6679e0058dfa123fb065d97b158b71959c0e048e7972bbb82ba0f"}, - {file = "grpcio_tools-1.60.0-cp311-cp311-win32.whl", hash = "sha256:bd2a17b0193fbe4793c215d63ce1e01ae00a8183d81d7c04e77e1dfafc4b2b8a"}, - {file = "grpcio_tools-1.60.0-cp311-cp311-win_amd64.whl", hash = "sha256:b22b1299b666eebd5752ba7719da536075eae3053abcf2898b65f763c314d9da"}, - {file = "grpcio_tools-1.60.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:74025fdd6d1cb7ba4b5d087995339e9a09f0c16cf15dfe56368b23e41ffeaf7a"}, - {file = "grpcio_tools-1.60.0-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:5a907a4f1ffba86501b2cdb8682346249ea032b922fc69a92f082ba045cca548"}, - {file = "grpcio_tools-1.60.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:1fbb9554466d560472f07d906bfc8dcaf52f365c2a407015185993e30372a886"}, - {file = "grpcio_tools-1.60.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f10ef47460ce3c6fd400f05fe757b90df63486c9b84d1ecad42dcc5f80c8ac14"}, - {file = "grpcio_tools-1.60.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:321b18f42a70813545e416ddcb8bf20defa407a8114906711c9710a69596ceda"}, - {file = "grpcio_tools-1.60.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:081336d8258f1a56542aa8a7a5dec99a2b38d902e19fbdd744594783301b0210"}, - {file = "grpcio_tools-1.60.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:addc9b23d6ff729d9f83d4a2846292d4c84f5eb2ec38f08489a6a0d66ac2b91e"}, - {file = "grpcio_tools-1.60.0-cp312-cp312-win32.whl", hash = "sha256:e87cabac7969bdde309575edc2456357667a1b28262b2c1f12580ef48315b19d"}, - {file = "grpcio_tools-1.60.0-cp312-cp312-win_amd64.whl", hash = "sha256:e70d867c120d9849093b0ac24d861e378bc88af2552e743d83b9f642d2caa7c2"}, - {file = "grpcio_tools-1.60.0-cp37-cp37m-linux_armv7l.whl", hash = "sha256:559ce714fe212aaf4abbe1493c5bb8920def00cc77ce0d45266f4fd9d8b3166f"}, - {file = "grpcio_tools-1.60.0-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:7a5263a0f2ddb7b1cfb2349e392cfc4f318722e0f48f886393e06946875d40f3"}, - {file = "grpcio_tools-1.60.0-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:18976684a931ca4bcba65c78afa778683aefaae310f353e198b1823bf09775a0"}, - {file = "grpcio_tools-1.60.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5c519a0d4ba1ab44a004fa144089738c59278233e2010b2cf4527dc667ff297"}, - {file = "grpcio_tools-1.60.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6170873b1e5b6580ebb99e87fb6e4ea4c48785b910bd7af838cc6e44b2bccb04"}, - {file = "grpcio_tools-1.60.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:fb4df80868b3e397d5fbccc004c789d2668b622b51a9d2387b4c89c80d31e2c5"}, - {file = "grpcio_tools-1.60.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dba6e32c87b4af29b5f475fb2f470f7ee3140bfc128644f17c6c59ddeb670680"}, - {file = "grpcio_tools-1.60.0-cp37-cp37m-win_amd64.whl", hash = "sha256:f610384dee4b1ca705e8da66c5b5fe89a2de3d165c5282c3d1ddf40cb18924e4"}, - {file = "grpcio_tools-1.60.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:4041538f55aad5b3ae7e25ab314d7995d689e968bfc8aa169d939a3160b1e4c6"}, - {file = "grpcio_tools-1.60.0-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:2fb4cf74bfe1e707cf10bc9dd38a1ebaa145179453d150febb121c7e9cd749bf"}, - {file = "grpcio_tools-1.60.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:2fd1671c52f96e79a2302c8b1c1f78b8a561664b8b3d6946f20d8f1cc6b4225a"}, - {file = "grpcio_tools-1.60.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd1e68c232fe01dd5312a8dbe52c50ecd2b5991d517d7f7446af4ba6334ba872"}, - {file = "grpcio_tools-1.60.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17a32b3da4fc0798cdcec0a9c974ac2a1e98298f151517bf9148294a3b1a5742"}, - {file = "grpcio_tools-1.60.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9970d384fb0c084b00945ef57d98d57a8d32be106d8f0bd31387f7cbfe411b5b"}, - {file = "grpcio_tools-1.60.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5ce6bbd4936977ec1114f2903eb4342781960d521b0d82f73afedb9335251f6f"}, - {file = "grpcio_tools-1.60.0-cp38-cp38-win32.whl", hash = "sha256:2e00de389729ca8d8d1a63c2038703078a887ff738dc31be640b7da9c26d0d4f"}, - {file = "grpcio_tools-1.60.0-cp38-cp38-win_amd64.whl", hash = "sha256:6192184b1f99372ff1d9594bd4b12264e3ff26440daba7eb043726785200ff77"}, - {file = "grpcio_tools-1.60.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:eae27f9b16238e2aaee84c77b5923c6924d6dccb0bdd18435bf42acc8473ae1a"}, - {file = "grpcio_tools-1.60.0-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:b96981f3a31b85074b73d97c8234a5ed9053d65a36b18f4a9c45a2120a5b7a0a"}, - {file = "grpcio_tools-1.60.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:1748893efd05cf4a59a175d7fa1e4fbb652f4d84ccaa2109f7869a2be48ed25e"}, - {file = "grpcio_tools-1.60.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a6fe752205caae534f29fba907e2f59ff79aa42c6205ce9a467e9406cbac68c"}, - {file = "grpcio_tools-1.60.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3456df087ea61a0972a5bc165aed132ed6ddcc63f5749e572f9fff84540bdbad"}, - {file = "grpcio_tools-1.60.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f3d916606dcf5610d4367918245b3d9d8cd0d2ec0b7043d1bbb8c50fe9815c3a"}, - {file = "grpcio_tools-1.60.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fc01bc1079279ec342f0f1b6a107b3f5dc3169c33369cf96ada6e2e171f74e86"}, - {file = "grpcio_tools-1.60.0-cp39-cp39-win32.whl", hash = "sha256:2dd01257e4feff986d256fa0bac9f56de59dc735eceeeb83de1c126e2e91f653"}, - {file = "grpcio_tools-1.60.0-cp39-cp39-win_amd64.whl", hash = "sha256:1b93ae8ffd18e9af9a965ebca5fa521e89066267de7abdde20721edc04e42721"}, + {file = "grpcio-tools-1.60.1.tar.gz", hash = "sha256:da08224ab8675c6d464b988bd8ca02cccd2bf0275bceefe8f6219bfd4a4f5e85"}, + {file = "grpcio_tools-1.60.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:184b27333b627a7cc0972fb70d21a8bb7c02ac4a6febc16768d78ea8ff883ddd"}, + {file = "grpcio_tools-1.60.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:18d7737f29ef5bbe3352547d0eccd080807834f00df223867dfc860bf81e9180"}, + {file = "grpcio_tools-1.60.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:cc8ba358d2c658c6ecbc58e779bf0fc5a673fecac015a70db27fc5b4d37b76b6"}, + {file = "grpcio_tools-1.60.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2973f75e8ba5c551033a1d59cc97654f6f386deaf2559082011d245d7ed87bba"}, + {file = "grpcio_tools-1.60.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28ae665113affebdd109247386786e5ab4dccfcfad1b5f68e9cce2e326b57ee6"}, + {file = "grpcio_tools-1.60.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5c7ed086fef5ff59f46d53a052b1934b73e0f7d12365d656d6af3a88057d5a3e"}, + {file = "grpcio_tools-1.60.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8540f6480428a52614db71dd6394f52cbc0d2565b5ea1136a982f26390a42c7a"}, + {file = "grpcio_tools-1.60.1-cp310-cp310-win32.whl", hash = "sha256:5b4a939097005531edec331f22d0b82bff26e71ede009354d2f375b5d41e74f0"}, + {file = "grpcio_tools-1.60.1-cp310-cp310-win_amd64.whl", hash = "sha256:075bb67895970f96aabc1761ca674bf4db193f8fcad387f08e50402023b5f953"}, + {file = "grpcio_tools-1.60.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:284749d20fb22418f17d3d351b9eb838caf4a0393a9cb02c36e5c32fa4bbe9db"}, + {file = "grpcio_tools-1.60.1-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:b1041377cf32ee2338284ee26e6b9c10f9ea7728092376b19803dcb9b91d510d"}, + {file = "grpcio_tools-1.60.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:e529cd3d4109a6f4a3f7bdaca68946eb33734e2d7ffe861785a0586abe99ee67"}, + {file = "grpcio_tools-1.60.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31294b534f25f02ead204e58dcbe0e5437a95a1a6f276bb9378905595b02ff6d"}, + {file = "grpcio_tools-1.60.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fb6f4d2df0388c35c2804ba170f511238a681b679ead013bfe5e39d0ea9cf48"}, + {file = "grpcio_tools-1.60.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:40cd8268a675269ce59c4fa50877597ec638bb1099c52237bb726c8ac9791868"}, + {file = "grpcio_tools-1.60.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:985ac476da365267a2367ab20060f9096fbfc2e190fb02dd394f9ec05edf03ca"}, + {file = "grpcio_tools-1.60.1-cp311-cp311-win32.whl", hash = "sha256:bd85f6c368b93ae45edf8568473053cb1cc075ef3489efb18f9832d4ecce062f"}, + {file = "grpcio_tools-1.60.1-cp311-cp311-win_amd64.whl", hash = "sha256:c20e752ff5057758845f4e5c7a298739bfba291f373ed18ea9c7c7acbe69e8ab"}, + {file = "grpcio_tools-1.60.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:aafc94616c5f89c891d859057b194a153c451f9921053454e9d7d4cbf79047eb"}, + {file = "grpcio_tools-1.60.1-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:9bba347000f57dae8aea79c0d76ef7d72895597524d30d0170c7d1974a3a03f3"}, + {file = "grpcio_tools-1.60.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:1e96a532d38411f0543fe1903ff522f7142a9901afb0ed94de58d79caf1905be"}, + {file = "grpcio_tools-1.60.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ea6e397d87f458bb2c387a4a6e1b65df74ce5b5194a1f16850c38309012e981"}, + {file = "grpcio_tools-1.60.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aeecd5b8faa2aab67e6c8b8a57e888c00ce70d39f331ede0a21312e92def1a6"}, + {file = "grpcio_tools-1.60.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:d2c26ce5f774c98bd2d3d8d1703048394018b55d297ebdb41ed2ba35b9a34f68"}, + {file = "grpcio_tools-1.60.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:214281cdafb7acfdcde848eca2de7c888a6e2b5cd25ab579712b965ea09a9cd4"}, + {file = "grpcio_tools-1.60.1-cp312-cp312-win32.whl", hash = "sha256:8c4b917aa4fcdc77990773063f0f14540aab8d4a8bf6c862b964a45d891a31d2"}, + {file = "grpcio_tools-1.60.1-cp312-cp312-win_amd64.whl", hash = "sha256:0aa34c7c21cff2177a4096b2b0d51dfbc9f8a41f929847a434e89b352c5a215d"}, + {file = "grpcio_tools-1.60.1-cp37-cp37m-linux_armv7l.whl", hash = "sha256:acdba77584981fe799104aa545d9d97910bcf88c69b668b768c1f3e7d7e5afac"}, + {file = "grpcio_tools-1.60.1-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:2a7fa55bc62d4b8ebe6fb26f8cf89df3cf3b504eb6c5f3a2f0174689d35fddb0"}, + {file = "grpcio_tools-1.60.1-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:dffa326cf901fe08a0e218d9fdf593f12276088a8caa07fcbec7d051149cf9ef"}, + {file = "grpcio_tools-1.60.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf945bd22f396c0d0c691e0990db2bfc4e77816b1edc2aea8a69c35ae721aac9"}, + {file = "grpcio_tools-1.60.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6801cfc5a85f0fb6fd12cade45942aaa1c814422328d594d12d364815fe34123"}, + {file = "grpcio_tools-1.60.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f95bdc6c7c50b7fc442e53537bc5b4eb8cab2a671c1da80d40b5a4ab1fd5d416"}, + {file = "grpcio_tools-1.60.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:402efeec36d8b12b792bae8a900085416fc2f57a34b599445ace2e847b6b0d75"}, + {file = "grpcio_tools-1.60.1-cp37-cp37m-win_amd64.whl", hash = "sha256:af88a2062b9c35034a80b25f289034b9c3c00c42bb88efaa465503a06fbd6a87"}, + {file = "grpcio_tools-1.60.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:46b495bae31c5d3f6ac0240eb848f0642b5410f80dff2aacdea20cdea3938c1d"}, + {file = "grpcio_tools-1.60.1-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:b5ae375207af9aa82f516dcd513d2e0c83690b7788d45844daad846ed87550f8"}, + {file = "grpcio_tools-1.60.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:15f13e8f3d77b96adcb1e3615acec5b100bd836c6010c58a51465bcb9c06d128"}, + {file = "grpcio_tools-1.60.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c354505e6a3d170da374f20404ea6a78135502df4f5534e5c532bdf24c4cc2a5"}, + {file = "grpcio_tools-1.60.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8cfab27ba2bd36a3e3b522aed686133531e8b919703d0247a0885dae8815317"}, + {file = "grpcio_tools-1.60.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b6ef213cb0aecb2832ee82a2eac32f29f31f50b17ce020604d82205096a6bd0c"}, + {file = "grpcio_tools-1.60.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b62cb2d43a7f0eacc6a6962dfff7c2564874012e1a72ae4167e762f449e2912"}, + {file = "grpcio_tools-1.60.1-cp38-cp38-win32.whl", hash = "sha256:3fcabf484720a9fa1690e2825fc940027a05a0c79a1075a730008ef634bd8ad2"}, + {file = "grpcio_tools-1.60.1-cp38-cp38-win_amd64.whl", hash = "sha256:22ce3e3d861321d208d8bfd6161ab976623520b179712c90b2c175151463a6b1"}, + {file = "grpcio_tools-1.60.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:4e66fe204da15e08e599adb3060109a42927c0868fe8933e2d341ea649eceb03"}, + {file = "grpcio_tools-1.60.1-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:c1047bd831de5d9da761e9dc246988d5f07d722186938dfd5f34807398101010"}, + {file = "grpcio_tools-1.60.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:eba5fafd70585fbd4cb6ae45e3c5e11d8598e2426c9f289b78f682c0606e81cb"}, + {file = "grpcio_tools-1.60.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bba7230c60238c7a4ffa29f1aff6d78edb41f2c79cbe4443406472b1c80ccb5d"}, + {file = "grpcio_tools-1.60.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2bb8efc2cd64bd8f2779b426dd7e94e60924078ba5150cbbb60a846e62d1ed2"}, + {file = "grpcio_tools-1.60.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:26f91161a91f1601777751230eaaafdf416fed08a15c3ba2ae391088e4a906c6"}, + {file = "grpcio_tools-1.60.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2c19be2bba5583e30f88bb5d71b430176c396f0d6d0db3785e5845bfa3d28cd2"}, + {file = "grpcio_tools-1.60.1-cp39-cp39-win32.whl", hash = "sha256:9aadc9c00baa2064baa4414cff7c269455449f14805a355226674d89c507342c"}, + {file = "grpcio_tools-1.60.1-cp39-cp39-win_amd64.whl", hash = "sha256:652b08c9fef39186ce4f97f05f5440c0ed41f117db0f7d6cb0e0d75dbc6afd3f"}, ] [package.dependencies] -grpcio = ">=1.60.0" +grpcio = ">=1.60.1" protobuf = ">=4.21.6,<5.0dev" setuptools = "*" @@ -1448,33 +1431,27 @@ files = [ [[package]] name = "isort" -version = "5.13.0" +version = "5.13.2" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.8.0" files = [ - {file = "isort-5.13.0-py3-none-any.whl", hash = "sha256:15e0e937819b350bc256a7ae13bb25f4fe4f8871a0bc335b20c3627dba33f458"}, - {file = "isort-5.13.0.tar.gz", hash = "sha256:d67f78c6a1715f224cca46b29d740037bdb6eea15323a133e897cda15876147b"}, + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, ] -[package.dependencies] -pip-api = "*" -pipreqs = "*" -requirementslib = "*" - [package.extras] colors = ["colorama (>=0.4.6)"] -plugins = ["setuptools"] [[package]] name = "jsonschema" -version = "4.20.0" +version = "4.21.1" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema-4.20.0-py3-none-any.whl", hash = "sha256:ed6231f0429ecf966f5bc8dfef245998220549cbbcf140f913b7464c52c3b6b3"}, - {file = "jsonschema-4.20.0.tar.gz", hash = "sha256:4f614fd46d8d61258610998997743ec5492a648b33cf478c1ddc23ed4598a5fa"}, + {file = "jsonschema-4.21.1-py3-none-any.whl", hash = "sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f"}, + {file = "jsonschema-4.21.1.tar.gz", hash = "sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5"}, ] [package.dependencies] @@ -1489,13 +1466,13 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- [[package]] name = "jsonschema-specifications" -version = "2023.11.2" +version = "2023.12.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema_specifications-2023.11.2-py3-none-any.whl", hash = "sha256:e74ba7c0a65e8cb49dc26837d6cfe576557084a8b423ed16a420984228104f93"}, - {file = "jsonschema_specifications-2023.11.2.tar.gz", hash = "sha256:9472fc4fea474cd74bea4a2b190daeccb5a9e4db2ea80efcf7a1b582fc9a81b8"}, + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, ] [package.dependencies] @@ -1608,96 +1585,112 @@ files = [ [[package]] name = "mnemonic" -version = "0.20" +version = "0.21" description = "Implementation of Bitcoin BIP-0039" optional = false -python-versions = ">=3.5" +python-versions = ">=3.8.1" files = [ - {file = "mnemonic-0.20-py3-none-any.whl", hash = "sha256:acd2168872d0379e7a10873bb3e12bf6c91b35de758135c4fbd1015ef18fafc5"}, - {file = "mnemonic-0.20.tar.gz", hash = "sha256:7c6fb5639d779388027a77944680aee4870f0fcd09b1e42a5525ee2ce4c625f6"}, + {file = "mnemonic-0.21-py3-none-any.whl", hash = "sha256:72dc9de16ec5ef47287237b9b6943da11647a03fe7cf1f139fc3d7c4a7439288"}, + {file = "mnemonic-0.21.tar.gz", hash = "sha256:1fe496356820984f45559b1540c80ff10de448368929b9c60a2b55744cc88acf"}, ] [[package]] name = "multidict" -version = "6.0.4" +version = "6.0.5" description = "multidict implementation" optional = false python-versions = ">=3.7" files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, ] [[package]] @@ -1760,103 +1753,30 @@ files = [ {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] -[[package]] -name = "pep517" -version = "0.13.1" -description = "Wrappers to build Python packages using PEP 517 hooks" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pep517-0.13.1-py3-none-any.whl", hash = "sha256:31b206f67165b3536dd577c5c3f1518e8fbaf38cbc57efff8369a392feff1721"}, - {file = "pep517-0.13.1.tar.gz", hash = "sha256:1b2fa2ffd3938bb4beffe5d6146cbcb2bda996a5a4da9f31abffd8b24e07b317"}, -] - -[package.dependencies] -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[[package]] -name = "pip" -version = "23.3.1" -description = "The PyPA recommended tool for installing Python packages." -optional = false -python-versions = ">=3.7" -files = [ - {file = "pip-23.3.1-py3-none-any.whl", hash = "sha256:55eb67bb6171d37447e82213be585b75fe2b12b359e993773aca4de9247a052b"}, - {file = "pip-23.3.1.tar.gz", hash = "sha256:1fcaa041308d01f14575f6d0d2ea4b75a3e2871fe4f9c694976f908768e14174"}, -] - -[[package]] -name = "pip-api" -version = "0.0.30" -description = "An unofficial, importable pip API" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pip-api-0.0.30.tar.gz", hash = "sha256:a05df2c7aa9b7157374bcf4273544201a0c7bae60a9c65bcf84f3959ef3896f3"}, - {file = "pip_api-0.0.30-py3-none-any.whl", hash = "sha256:2a0314bd31522eb9ffe8a99668b0d07fee34ebc537931e7b6483001dbedcbdc9"}, -] - -[package.dependencies] -pip = "*" - -[[package]] -name = "pipreqs" -version = "0.4.13" -description = "Pip requirements.txt generator based on imports in project" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pipreqs-0.4.13-py2.py3-none-any.whl", hash = "sha256:e522b9ed54aa3e8b7978ff251ab7a9af2f75d2cd8de4c102e881b666a79a308e"}, - {file = "pipreqs-0.4.13.tar.gz", hash = "sha256:a17f167880b6921be37533ce4c81ddc6e22b465c107aad557db43b1add56a99b"}, -] - -[package.dependencies] -docopt = "*" -yarg = "*" - [[package]] name = "platformdirs" -version = "4.1.0" +version = "4.2.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, - {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, ] [package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] - -[[package]] -name = "plette" -version = "0.4.4" -description = "Structured Pipfile and Pipfile.lock models." -optional = false -python-versions = ">=3.7" -files = [ - {file = "plette-0.4.4-py2.py3-none-any.whl", hash = "sha256:42d68ce8c6b966874b68758d87d7f20fcff2eff0d861903eea1062126be4d98f"}, - {file = "plette-0.4.4.tar.gz", hash = "sha256:06b8c09eb90293ad0b8101cb5c95c4ea53e9b2b582901845d0904ff02d237454"}, -] - -[package.dependencies] -cerberus = {version = "*", optional = true, markers = "extra == \"validation\""} -tomlkit = "*" - -[package.extras] -tests = ["pytest", "pytest-cov", "pytest-xdist"] -validation = ["cerberus"] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] [[package]] name = "pluggy" -version = "1.3.0" +version = "1.4.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" files = [ - {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, - {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, ] [package.extras] @@ -1883,22 +1803,22 @@ virtualenv = ">=20.10.0" [[package]] name = "protobuf" -version = "4.25.1" +version = "4.25.2" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "protobuf-4.25.1-cp310-abi3-win32.whl", hash = "sha256:193f50a6ab78a970c9b4f148e7c750cfde64f59815e86f686c22e26b4fe01ce7"}, - {file = "protobuf-4.25.1-cp310-abi3-win_amd64.whl", hash = "sha256:3497c1af9f2526962f09329fd61a36566305e6c72da2590ae0d7d1322818843b"}, - {file = "protobuf-4.25.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:0bf384e75b92c42830c0a679b0cd4d6e2b36ae0cf3dbb1e1dfdda48a244f4bcd"}, - {file = "protobuf-4.25.1-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:0f881b589ff449bf0b931a711926e9ddaad3b35089cc039ce1af50b21a4ae8cb"}, - {file = "protobuf-4.25.1-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:ca37bf6a6d0046272c152eea90d2e4ef34593aaa32e8873fc14c16440f22d4b7"}, - {file = "protobuf-4.25.1-cp38-cp38-win32.whl", hash = "sha256:abc0525ae2689a8000837729eef7883b9391cd6aa7950249dcf5a4ede230d5dd"}, - {file = "protobuf-4.25.1-cp38-cp38-win_amd64.whl", hash = "sha256:1484f9e692091450e7edf418c939e15bfc8fc68856e36ce399aed6889dae8bb0"}, - {file = "protobuf-4.25.1-cp39-cp39-win32.whl", hash = "sha256:8bdbeaddaac52d15c6dce38c71b03038ef7772b977847eb6d374fc86636fa510"}, - {file = "protobuf-4.25.1-cp39-cp39-win_amd64.whl", hash = "sha256:becc576b7e6b553d22cbdf418686ee4daa443d7217999125c045ad56322dda10"}, - {file = "protobuf-4.25.1-py3-none-any.whl", hash = "sha256:a19731d5e83ae4737bb2a089605e636077ac001d18781b3cf489b9546c7c80d6"}, - {file = "protobuf-4.25.1.tar.gz", hash = "sha256:57d65074b4f5baa4ab5da1605c02be90ac20c8b40fb137d6a8df9f416b0d0ce2"}, + {file = "protobuf-4.25.2-cp310-abi3-win32.whl", hash = "sha256:b50c949608682b12efb0b2717f53256f03636af5f60ac0c1d900df6213910fd6"}, + {file = "protobuf-4.25.2-cp310-abi3-win_amd64.whl", hash = "sha256:8f62574857ee1de9f770baf04dde4165e30b15ad97ba03ceac65f760ff018ac9"}, + {file = "protobuf-4.25.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:2db9f8fa64fbdcdc93767d3cf81e0f2aef176284071507e3ede160811502fd3d"}, + {file = "protobuf-4.25.2-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:10894a2885b7175d3984f2be8d9850712c57d5e7587a2410720af8be56cdaf62"}, + {file = "protobuf-4.25.2-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:fc381d1dd0516343f1440019cedf08a7405f791cd49eef4ae1ea06520bc1c020"}, + {file = "protobuf-4.25.2-cp38-cp38-win32.whl", hash = "sha256:33a1aeef4b1927431d1be780e87b641e322b88d654203a9e9d93f218ee359e61"}, + {file = "protobuf-4.25.2-cp38-cp38-win_amd64.whl", hash = "sha256:47f3de503fe7c1245f6f03bea7e8d3ec11c6c4a2ea9ef910e3221c8a15516d62"}, + {file = "protobuf-4.25.2-cp39-cp39-win32.whl", hash = "sha256:5e5c933b4c30a988b52e0b7c02641760a5ba046edc5e43d3b94a74c9fc57c1b3"}, + {file = "protobuf-4.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:d66a769b8d687df9024f2985d5137a337f957a0916cf5464d1513eee96a63ff0"}, + {file = "protobuf-4.25.2-py3-none-any.whl", hash = "sha256:a8b7a98d4ce823303145bf3c1a8bdb0f2f4642a414b196f04ad9853ed0c8f830"}, + {file = "protobuf-4.25.2.tar.gz", hash = "sha256:fe599e175cb347efc8ee524bcd4b902d11f7262c0e569ececcb89995c15f0a5e"}, ] [[package]] @@ -1925,181 +1845,45 @@ files = [ [[package]] name = "pycryptodome" -version = "3.19.0" +version = "3.20.0" description = "Cryptographic library for Python" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ - {file = "pycryptodome-3.19.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3006c44c4946583b6de24fe0632091c2653d6256b99a02a3db71ca06472ea1e4"}, - {file = "pycryptodome-3.19.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:7c760c8a0479a4042111a8dd2f067d3ae4573da286c53f13cf6f5c53a5c1f631"}, - {file = "pycryptodome-3.19.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:08ce3558af5106c632baf6d331d261f02367a6bc3733086ae43c0f988fe042db"}, - {file = "pycryptodome-3.19.0-cp27-cp27m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45430dfaf1f421cf462c0dd824984378bef32b22669f2635cb809357dbaab405"}, - {file = "pycryptodome-3.19.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:a9bcd5f3794879e91970f2bbd7d899780541d3ff439d8f2112441769c9f2ccea"}, - {file = "pycryptodome-3.19.0-cp27-cp27m-win32.whl", hash = "sha256:190c53f51e988dceb60472baddce3f289fa52b0ec38fbe5fd20dd1d0f795c551"}, - {file = "pycryptodome-3.19.0-cp27-cp27m-win_amd64.whl", hash = "sha256:22e0ae7c3a7f87dcdcf302db06ab76f20e83f09a6993c160b248d58274473bfa"}, - {file = "pycryptodome-3.19.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:7822f36d683f9ad7bc2145b2c2045014afdbbd1d9922a6d4ce1cbd6add79a01e"}, - {file = "pycryptodome-3.19.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:05e33267394aad6db6595c0ce9d427fe21552f5425e116a925455e099fdf759a"}, - {file = "pycryptodome-3.19.0-cp27-cp27mu-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:829b813b8ee00d9c8aba417621b94bc0b5efd18c928923802ad5ba4cf1ec709c"}, - {file = "pycryptodome-3.19.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:fc7a79590e2b5d08530175823a242de6790abc73638cc6dc9d2684e7be2f5e49"}, - {file = "pycryptodome-3.19.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:542f99d5026ac5f0ef391ba0602f3d11beef8e65aae135fa5b762f5ebd9d3bfb"}, - {file = "pycryptodome-3.19.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:61bb3ccbf4bf32ad9af32da8badc24e888ae5231c617947e0f5401077f8b091f"}, - {file = "pycryptodome-3.19.0-cp35-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d49a6c715d8cceffedabb6adb7e0cbf41ae1a2ff4adaeec9432074a80627dea1"}, - {file = "pycryptodome-3.19.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e249a784cc98a29c77cea9df54284a44b40cafbfae57636dd2f8775b48af2434"}, - {file = "pycryptodome-3.19.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d033947e7fd3e2ba9a031cb2d267251620964705a013c5a461fa5233cc025270"}, - {file = "pycryptodome-3.19.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:84c3e4fffad0c4988aef0d5591be3cad4e10aa7db264c65fadbc633318d20bde"}, - {file = "pycryptodome-3.19.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:139ae2c6161b9dd5d829c9645d781509a810ef50ea8b657e2257c25ca20efe33"}, - {file = "pycryptodome-3.19.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:5b1986c761258a5b4332a7f94a83f631c1ffca8747d75ab8395bf2e1b93283d9"}, - {file = "pycryptodome-3.19.0-cp35-abi3-win32.whl", hash = "sha256:536f676963662603f1f2e6ab01080c54d8cd20f34ec333dcb195306fa7826997"}, - {file = "pycryptodome-3.19.0-cp35-abi3-win_amd64.whl", hash = "sha256:04dd31d3b33a6b22ac4d432b3274588917dcf850cc0c51c84eca1d8ed6933810"}, - {file = "pycryptodome-3.19.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:8999316e57abcbd8085c91bc0ef75292c8618f41ca6d2b6132250a863a77d1e7"}, - {file = "pycryptodome-3.19.0-pp27-pypy_73-win32.whl", hash = "sha256:a0ab84755f4539db086db9ba9e9f3868d2e3610a3948cbd2a55e332ad83b01b0"}, - {file = "pycryptodome-3.19.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0101f647d11a1aae5a8ce4f5fad6644ae1b22bb65d05accc7d322943c69a74a6"}, - {file = "pycryptodome-3.19.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c1601e04d32087591d78e0b81e1e520e57a92796089864b20e5f18c9564b3fa"}, - {file = "pycryptodome-3.19.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:506c686a1eee6c00df70010be3b8e9e78f406af4f21b23162bbb6e9bdf5427bc"}, - {file = "pycryptodome-3.19.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7919ccd096584b911f2a303c593280869ce1af9bf5d36214511f5e5a1bed8c34"}, - {file = "pycryptodome-3.19.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:560591c0777f74a5da86718f70dfc8d781734cf559773b64072bbdda44b3fc3e"}, - {file = "pycryptodome-3.19.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1cc2f2ae451a676def1a73c1ae9120cd31af25db3f381893d45f75e77be2400"}, - {file = "pycryptodome-3.19.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:17940dcf274fcae4a54ec6117a9ecfe52907ed5e2e438fe712fe7ca502672ed5"}, - {file = "pycryptodome-3.19.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d04f5f623a280fbd0ab1c1d8ecbd753193ab7154f09b6161b0f857a1a676c15f"}, - {file = "pycryptodome-3.19.0.tar.gz", hash = "sha256:bc35d463222cdb4dbebd35e0784155c81e161b9284e567e7e933d722e533331e"}, -] - -[[package]] -name = "pydantic" -version = "2.5.2" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydantic-2.5.2-py3-none-any.whl", hash = "sha256:80c50fb8e3dcecfddae1adbcc00ec5822918490c99ab31f6cf6140ca1c1429f0"}, - {file = "pydantic-2.5.2.tar.gz", hash = "sha256:ff177ba64c6faf73d7afa2e8cad38fd456c0dbe01c9954e71038001cd15a6edd"}, -] - -[package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.14.5" -typing-extensions = ">=4.6.1" - -[package.extras] -email = ["email-validator (>=2.0.0)"] - -[[package]] -name = "pydantic-core" -version = "2.14.5" -description = "" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydantic_core-2.14.5-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:7e88f5696153dc516ba6e79f82cc4747e87027205f0e02390c21f7cb3bd8abfd"}, - {file = "pydantic_core-2.14.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4641e8ad4efb697f38a9b64ca0523b557c7931c5f84e0fd377a9a3b05121f0de"}, - {file = "pydantic_core-2.14.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:774de879d212db5ce02dfbf5b0da9a0ea386aeba12b0b95674a4ce0593df3d07"}, - {file = "pydantic_core-2.14.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ebb4e035e28f49b6f1a7032920bb9a0c064aedbbabe52c543343d39341a5b2a3"}, - {file = "pydantic_core-2.14.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b53e9ad053cd064f7e473a5f29b37fc4cc9dc6d35f341e6afc0155ea257fc911"}, - {file = "pydantic_core-2.14.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aa1768c151cf562a9992462239dfc356b3d1037cc5a3ac829bb7f3bda7cc1f9"}, - {file = "pydantic_core-2.14.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eac5c82fc632c599f4639a5886f96867ffced74458c7db61bc9a66ccb8ee3113"}, - {file = "pydantic_core-2.14.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2ae91f50ccc5810b2f1b6b858257c9ad2e08da70bf890dee02de1775a387c66"}, - {file = "pydantic_core-2.14.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6b9ff467ffbab9110e80e8c8de3bcfce8e8b0fd5661ac44a09ae5901668ba997"}, - {file = "pydantic_core-2.14.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:61ea96a78378e3bd5a0be99b0e5ed00057b71f66115f5404d0dae4819f495093"}, - {file = "pydantic_core-2.14.5-cp310-none-win32.whl", hash = "sha256:bb4c2eda937a5e74c38a41b33d8c77220380a388d689bcdb9b187cf6224c9720"}, - {file = "pydantic_core-2.14.5-cp310-none-win_amd64.whl", hash = "sha256:b7851992faf25eac90bfcb7bfd19e1f5ffa00afd57daec8a0042e63c74a4551b"}, - {file = "pydantic_core-2.14.5-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:4e40f2bd0d57dac3feb3a3aed50f17d83436c9e6b09b16af271b6230a2915459"}, - {file = "pydantic_core-2.14.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ab1cdb0f14dc161ebc268c09db04d2c9e6f70027f3b42446fa11c153521c0e88"}, - {file = "pydantic_core-2.14.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aae7ea3a1c5bb40c93cad361b3e869b180ac174656120c42b9fadebf685d121b"}, - {file = "pydantic_core-2.14.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:60b7607753ba62cf0739177913b858140f11b8af72f22860c28eabb2f0a61937"}, - {file = "pydantic_core-2.14.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2248485b0322c75aee7565d95ad0e16f1c67403a470d02f94da7344184be770f"}, - {file = "pydantic_core-2.14.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:823fcc638f67035137a5cd3f1584a4542d35a951c3cc68c6ead1df7dac825c26"}, - {file = "pydantic_core-2.14.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96581cfefa9123accc465a5fd0cc833ac4d75d55cc30b633b402e00e7ced00a6"}, - {file = "pydantic_core-2.14.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a33324437018bf6ba1bb0f921788788641439e0ed654b233285b9c69704c27b4"}, - {file = "pydantic_core-2.14.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9bd18fee0923ca10f9a3ff67d4851c9d3e22b7bc63d1eddc12f439f436f2aada"}, - {file = "pydantic_core-2.14.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:853a2295c00f1d4429db4c0fb9475958543ee80cfd310814b5c0ef502de24dda"}, - {file = "pydantic_core-2.14.5-cp311-none-win32.whl", hash = "sha256:cb774298da62aea5c80a89bd58c40205ab4c2abf4834453b5de207d59d2e1651"}, - {file = "pydantic_core-2.14.5-cp311-none-win_amd64.whl", hash = "sha256:e87fc540c6cac7f29ede02e0f989d4233f88ad439c5cdee56f693cc9c1c78077"}, - {file = "pydantic_core-2.14.5-cp311-none-win_arm64.whl", hash = "sha256:57d52fa717ff445cb0a5ab5237db502e6be50809b43a596fb569630c665abddf"}, - {file = "pydantic_core-2.14.5-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:e60f112ac88db9261ad3a52032ea46388378034f3279c643499edb982536a093"}, - {file = "pydantic_core-2.14.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6e227c40c02fd873c2a73a98c1280c10315cbebe26734c196ef4514776120aeb"}, - {file = "pydantic_core-2.14.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0cbc7fff06a90bbd875cc201f94ef0ee3929dfbd5c55a06674b60857b8b85ed"}, - {file = "pydantic_core-2.14.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:103ef8d5b58596a731b690112819501ba1db7a36f4ee99f7892c40da02c3e189"}, - {file = "pydantic_core-2.14.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c949f04ecad823f81b1ba94e7d189d9dfb81edbb94ed3f8acfce41e682e48cef"}, - {file = "pydantic_core-2.14.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1452a1acdf914d194159439eb21e56b89aa903f2e1c65c60b9d874f9b950e5d"}, - {file = "pydantic_core-2.14.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb4679d4c2b089e5ef89756bc73e1926745e995d76e11925e3e96a76d5fa51fc"}, - {file = "pydantic_core-2.14.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf9d3fe53b1ee360e2421be95e62ca9b3296bf3f2fb2d3b83ca49ad3f925835e"}, - {file = "pydantic_core-2.14.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:70f4b4851dbb500129681d04cc955be2a90b2248d69273a787dda120d5cf1f69"}, - {file = "pydantic_core-2.14.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:59986de5710ad9613ff61dd9b02bdd2f615f1a7052304b79cc8fa2eb4e336d2d"}, - {file = "pydantic_core-2.14.5-cp312-none-win32.whl", hash = "sha256:699156034181e2ce106c89ddb4b6504c30db8caa86e0c30de47b3e0654543260"}, - {file = "pydantic_core-2.14.5-cp312-none-win_amd64.whl", hash = "sha256:5baab5455c7a538ac7e8bf1feec4278a66436197592a9bed538160a2e7d11e36"}, - {file = "pydantic_core-2.14.5-cp312-none-win_arm64.whl", hash = "sha256:e47e9a08bcc04d20975b6434cc50bf82665fbc751bcce739d04a3120428f3e27"}, - {file = "pydantic_core-2.14.5-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:af36f36538418f3806048f3b242a1777e2540ff9efaa667c27da63d2749dbce0"}, - {file = "pydantic_core-2.14.5-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:45e95333b8418ded64745f14574aa9bfc212cb4fbeed7a687b0c6e53b5e188cd"}, - {file = "pydantic_core-2.14.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e47a76848f92529879ecfc417ff88a2806438f57be4a6a8bf2961e8f9ca9ec7"}, - {file = "pydantic_core-2.14.5-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d81e6987b27bc7d101c8597e1cd2bcaa2fee5e8e0f356735c7ed34368c471550"}, - {file = "pydantic_core-2.14.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34708cc82c330e303f4ce87758828ef6e457681b58ce0e921b6e97937dd1e2a3"}, - {file = "pydantic_core-2.14.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:652c1988019752138b974c28f43751528116bcceadad85f33a258869e641d753"}, - {file = "pydantic_core-2.14.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e4d090e73e0725b2904fdbdd8d73b8802ddd691ef9254577b708d413bf3006e"}, - {file = "pydantic_core-2.14.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5c7d5b5005f177764e96bd584d7bf28d6e26e96f2a541fdddb934c486e36fd59"}, - {file = "pydantic_core-2.14.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a71891847f0a73b1b9eb86d089baee301477abef45f7eaf303495cd1473613e4"}, - {file = "pydantic_core-2.14.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a717aef6971208f0851a2420b075338e33083111d92041157bbe0e2713b37325"}, - {file = "pydantic_core-2.14.5-cp37-none-win32.whl", hash = "sha256:de790a3b5aa2124b8b78ae5faa033937a72da8efe74b9231698b5a1dd9be3405"}, - {file = "pydantic_core-2.14.5-cp37-none-win_amd64.whl", hash = "sha256:6c327e9cd849b564b234da821236e6bcbe4f359a42ee05050dc79d8ed2a91588"}, - {file = "pydantic_core-2.14.5-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:ef98ca7d5995a82f43ec0ab39c4caf6a9b994cb0b53648ff61716370eadc43cf"}, - {file = "pydantic_core-2.14.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6eae413494a1c3f89055da7a5515f32e05ebc1a234c27674a6956755fb2236f"}, - {file = "pydantic_core-2.14.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcf4e6d85614f7a4956c2de5a56531f44efb973d2fe4a444d7251df5d5c4dcfd"}, - {file = "pydantic_core-2.14.5-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6637560562134b0e17de333d18e69e312e0458ee4455bdad12c37100b7cad706"}, - {file = "pydantic_core-2.14.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:77fa384d8e118b3077cccfcaf91bf83c31fe4dc850b5e6ee3dc14dc3d61bdba1"}, - {file = "pydantic_core-2.14.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16e29bad40bcf97aac682a58861249ca9dcc57c3f6be22f506501833ddb8939c"}, - {file = "pydantic_core-2.14.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531f4b4252fac6ca476fbe0e6f60f16f5b65d3e6b583bc4d87645e4e5ddde331"}, - {file = "pydantic_core-2.14.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:074f3d86f081ce61414d2dc44901f4f83617329c6f3ab49d2bc6c96948b2c26b"}, - {file = "pydantic_core-2.14.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c2adbe22ab4babbca99c75c5d07aaf74f43c3195384ec07ccbd2f9e3bddaecec"}, - {file = "pydantic_core-2.14.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0f6116a558fd06d1b7c2902d1c4cf64a5bd49d67c3540e61eccca93f41418124"}, - {file = "pydantic_core-2.14.5-cp38-none-win32.whl", hash = "sha256:fe0a5a1025eb797752136ac8b4fa21aa891e3d74fd340f864ff982d649691867"}, - {file = "pydantic_core-2.14.5-cp38-none-win_amd64.whl", hash = "sha256:079206491c435b60778cf2b0ee5fd645e61ffd6e70c47806c9ed51fc75af078d"}, - {file = "pydantic_core-2.14.5-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:a6a16f4a527aae4f49c875da3cdc9508ac7eef26e7977952608610104244e1b7"}, - {file = "pydantic_core-2.14.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:abf058be9517dc877227ec3223f0300034bd0e9f53aebd63cf4456c8cb1e0863"}, - {file = "pydantic_core-2.14.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49b08aae5013640a3bfa25a8eebbd95638ec3f4b2eaf6ed82cf0c7047133f03b"}, - {file = "pydantic_core-2.14.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c2d97e906b4ff36eb464d52a3bc7d720bd6261f64bc4bcdbcd2c557c02081ed2"}, - {file = "pydantic_core-2.14.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3128e0bbc8c091ec4375a1828d6118bc20404883169ac95ffa8d983b293611e6"}, - {file = "pydantic_core-2.14.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88e74ab0cdd84ad0614e2750f903bb0d610cc8af2cc17f72c28163acfcf372a4"}, - {file = "pydantic_core-2.14.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c339dabd8ee15f8259ee0f202679b6324926e5bc9e9a40bf981ce77c038553db"}, - {file = "pydantic_core-2.14.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3387277f1bf659caf1724e1afe8ee7dbc9952a82d90f858ebb931880216ea955"}, - {file = "pydantic_core-2.14.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ba6b6b3846cfc10fdb4c971980a954e49d447cd215ed5a77ec8190bc93dd7bc5"}, - {file = "pydantic_core-2.14.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ca61d858e4107ce5e1330a74724fe757fc7135190eb5ce5c9d0191729f033209"}, - {file = "pydantic_core-2.14.5-cp39-none-win32.whl", hash = "sha256:ec1e72d6412f7126eb7b2e3bfca42b15e6e389e1bc88ea0069d0cc1742f477c6"}, - {file = "pydantic_core-2.14.5-cp39-none-win_amd64.whl", hash = "sha256:c0b97ec434041827935044bbbe52b03d6018c2897349670ff8fe11ed24d1d4ab"}, - {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:79e0a2cdbdc7af3f4aee3210b1172ab53d7ddb6a2d8c24119b5706e622b346d0"}, - {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:678265f7b14e138d9a541ddabbe033012a2953315739f8cfa6d754cc8063e8ca"}, - {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95b15e855ae44f0c6341ceb74df61b606e11f1087e87dcb7482377374aac6abe"}, - {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09b0e985fbaf13e6b06a56d21694d12ebca6ce5414b9211edf6f17738d82b0f8"}, - {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ad873900297bb36e4b6b3f7029d88ff9829ecdc15d5cf20161775ce12306f8a"}, - {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:2d0ae0d8670164e10accbeb31d5ad45adb71292032d0fdb9079912907f0085f4"}, - {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d37f8ec982ead9ba0a22a996129594938138a1503237b87318392a48882d50b7"}, - {file = "pydantic_core-2.14.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:35613015f0ba7e14c29ac6c2483a657ec740e5ac5758d993fdd5870b07a61d8b"}, - {file = "pydantic_core-2.14.5-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ab4ea451082e684198636565224bbb179575efc1658c48281b2c866bfd4ddf04"}, - {file = "pydantic_core-2.14.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ce601907e99ea5b4adb807ded3570ea62186b17f88e271569144e8cca4409c7"}, - {file = "pydantic_core-2.14.5-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb2ed8b3fe4bf4506d6dab3b93b83bbc22237e230cba03866d561c3577517d18"}, - {file = "pydantic_core-2.14.5-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70f947628e074bb2526ba1b151cee10e4c3b9670af4dbb4d73bc8a89445916b5"}, - {file = "pydantic_core-2.14.5-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4bc536201426451f06f044dfbf341c09f540b4ebdb9fd8d2c6164d733de5e634"}, - {file = "pydantic_core-2.14.5-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4791cf0f8c3104ac668797d8c514afb3431bc3305f5638add0ba1a5a37e0d88"}, - {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:038c9f763e650712b899f983076ce783175397c848da04985658e7628cbe873b"}, - {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:27548e16c79702f1e03f5628589c6057c9ae17c95b4c449de3c66b589ead0520"}, - {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c97bee68898f3f4344eb02fec316db93d9700fb1e6a5b760ffa20d71d9a46ce3"}, - {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9b759b77f5337b4ea024f03abc6464c9f35d9718de01cfe6bae9f2e139c397e"}, - {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:439c9afe34638ace43a49bf72d201e0ffc1a800295bed8420c2a9ca8d5e3dbb3"}, - {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:ba39688799094c75ea8a16a6b544eb57b5b0f3328697084f3f2790892510d144"}, - {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ccd4d5702bb90b84df13bd491be8d900b92016c5a455b7e14630ad7449eb03f8"}, - {file = "pydantic_core-2.14.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:81982d78a45d1e5396819bbb4ece1fadfe5f079335dd28c4ab3427cd95389944"}, - {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:7f8210297b04e53bc3da35db08b7302a6a1f4889c79173af69b72ec9754796b8"}, - {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:8c8a8812fe6f43a3a5b054af6ac2d7b8605c7bcab2804a8a7d68b53f3cd86e00"}, - {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:206ed23aecd67c71daf5c02c3cd19c0501b01ef3cbf7782db9e4e051426b3d0d"}, - {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2027d05c8aebe61d898d4cffd774840a9cb82ed356ba47a90d99ad768f39789"}, - {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:40180930807ce806aa71eda5a5a5447abb6b6a3c0b4b3b1b1962651906484d68"}, - {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:615a0a4bff11c45eb3c1996ceed5bdaa2f7b432425253a7c2eed33bb86d80abc"}, - {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5e412d717366e0677ef767eac93566582518fe8be923361a5c204c1a62eaafe"}, - {file = "pydantic_core-2.14.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:513b07e99c0a267b1d954243845d8a833758a6726a3b5d8948306e3fe14675e3"}, - {file = "pydantic_core-2.14.5.tar.gz", hash = "sha256:6d30226dfc816dd0fdf120cae611dd2215117e4f9b124af8c60ab9093b6e8e71"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:f0e6d631bae3f231d3634f91ae4da7a960f7ff87f2865b2d2b831af1dfb04e9a"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:baee115a9ba6c5d2709a1e88ffe62b73ecc044852a925dcb67713a288c4ec70f"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:417a276aaa9cb3be91f9014e9d18d10e840a7a9b9a9be64a42f553c5b50b4d1d"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a1250b7ea809f752b68e3e6f3fd946b5939a52eaeea18c73bdab53e9ba3c2dd"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:d5954acfe9e00bc83ed9f5cb082ed22c592fbbef86dc48b907238be64ead5c33"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-win32.whl", hash = "sha256:06d6de87c19f967f03b4cf9b34e538ef46e99a337e9a61a77dbe44b2cbcf0690"}, + {file = "pycryptodome-3.20.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ec0bb1188c1d13426039af8ffcb4dbe3aad1d7680c35a62d8eaf2a529b5d3d4f"}, + {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5601c934c498cd267640b57569e73793cb9a83506f7c73a8ec57a516f5b0b091"}, + {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d29daa681517f4bc318cd8a23af87e1f2a7bad2fe361e8aa29c77d652a065de4"}, + {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3427d9e5310af6680678f4cce149f54e0bb4af60101c7f2c16fdf878b39ccccc"}, + {file = "pycryptodome-3.20.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:3cd3ef3aee1079ae44afaeee13393cf68b1058f70576b11439483e34f93cf818"}, + {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac1c7c0624a862f2e53438a15c9259d1655325fc2ec4392e66dc46cdae24d044"}, + {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:76658f0d942051d12a9bd08ca1b6b34fd762a8ee4240984f7c06ddfb55eaf15a"}, + {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f35d6cee81fa145333137009d9c8ba90951d7d77b67c79cbe5f03c7eb74d8fe2"}, + {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cb39afede7055127e35a444c1c041d2e8d2f1f9c121ecef573757ba4cd2c3c"}, + {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a4c4dc60b78ec41d2afa392491d788c2e06edf48580fbfb0dd0f828af49d25"}, + {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fb3b87461fa35afa19c971b0a2b7456a7b1db7b4eba9a8424666104925b78128"}, + {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:acc2614e2e5346a4a4eab6e199203034924313626f9620b7b4b38e9ad74b7e0c"}, + {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:210ba1b647837bfc42dd5a813cdecb5b86193ae11a3f5d972b9a0ae2c7e9e4b4"}, + {file = "pycryptodome-3.20.0-cp35-abi3-win32.whl", hash = "sha256:8d6b98d0d83d21fb757a182d52940d028564efe8147baa9ce0f38d057104ae72"}, + {file = "pycryptodome-3.20.0-cp35-abi3-win_amd64.whl", hash = "sha256:9b3ae153c89a480a0ec402e23db8d8d84a3833b65fa4b15b81b83be9d637aab9"}, + {file = "pycryptodome-3.20.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:4401564ebf37dfde45d096974c7a159b52eeabd9969135f0426907db367a652a"}, + {file = "pycryptodome-3.20.0-pp27-pypy_73-win32.whl", hash = "sha256:ec1f93feb3bb93380ab0ebf8b859e8e5678c0f010d2d78367cf6bc30bfeb148e"}, + {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:acae12b9ede49f38eb0ef76fdec2df2e94aad85ae46ec85be3648a57f0a7db04"}, + {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f47888542a0633baff535a04726948e876bf1ed880fddb7c10a736fa99146ab3"}, + {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e0e4a987d38cfc2e71b4a1b591bae4891eeabe5fa0f56154f576e26287bfdea"}, + {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c18b381553638414b38705f07d1ef0a7cf301bc78a5f9bc17a957eb19446834b"}, + {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a60fedd2b37b4cb11ccb5d0399efe26db9e0dd149016c1cc6c8161974ceac2d6"}, + {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:405002eafad114a2f9a930f5db65feef7b53c4784495dd8758069b89baf68eab"}, + {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ab6ab0cb755154ad14e507d1df72de9897e99fd2d4922851a276ccc14f4f1a5"}, + {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:acf6e43fa75aca2d33e93409f2dafe386fe051818ee79ee8a3e21de9caa2ac9e"}, + {file = "pycryptodome-3.20.0.tar.gz", hash = "sha256:09609209ed7de61c2b560cc5c8c4fbf892f8b15b1faf7e4cbffac97db1fffda7"}, ] -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - [[package]] name = "pyflakes" version = "2.4.0" @@ -2128,13 +1912,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" -version = "7.4.3" +version = "7.4.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"}, - {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"}, + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, ] [package.dependencies] @@ -2150,17 +1934,17 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no [[package]] name = "pytest-asyncio" -version = "0.23.2" +version = "0.23.4" description = "Pytest support for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-asyncio-0.23.2.tar.gz", hash = "sha256:c16052382554c7b22d48782ab3438d5b10f8cf7a4bdcae7f0f67f097d95beecc"}, - {file = "pytest_asyncio-0.23.2-py3-none-any.whl", hash = "sha256:ea9021364e32d58f0be43b91c6233fb8d2224ccef2398d6837559e587682808f"}, + {file = "pytest-asyncio-0.23.4.tar.gz", hash = "sha256:2143d9d9375bf372a73260e4114541485e84fca350b0b6b92674ca56ff5f7ea2"}, + {file = "pytest_asyncio-0.23.4-py3-none-any.whl", hash = "sha256:b0079dfac14b60cd1ce4691fbfb1748fe939db7d0234b5aba97197d10fbe0fef"}, ] [package.dependencies] -pytest = ">=7.0.0" +pytest = ">=7.0.0,<8" [package.extras] docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] @@ -2198,6 +1982,20 @@ files = [ [package.dependencies] pytest = ">=3.6.0" +[[package]] +name = "python-dotenv" +version = "1.0.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "pyunormalize" version = "15.1.0" @@ -2292,13 +2090,13 @@ files = [ [[package]] name = "referencing" -version = "0.32.0" +version = "0.33.0" description = "JSON Referencing + Python" optional = false python-versions = ">=3.8" files = [ - {file = "referencing-0.32.0-py3-none-any.whl", hash = "sha256:bdcd3efb936f82ff86f993093f6da7435c7de69a3b3a5a06678a6050184bee99"}, - {file = "referencing-0.32.0.tar.gz", hash = "sha256:689e64fe121843dcfd57b71933318ef1f91188ffb45367332700a86ac8fd6161"}, + {file = "referencing-0.33.0-py3-none-any.whl", hash = "sha256:39240f2ecc770258f28b642dd47fd74bc8b02484de54e1882b74b35ebd779bd5"}, + {file = "referencing-0.33.0.tar.gz", hash = "sha256:c775fedf74bc0f9189c2a3be1c12fd03e8c23f4d371dce795df44e06c5b412f7"}, ] [package.dependencies] @@ -2307,99 +2105,104 @@ rpds-py = ">=0.7.0" [[package]] name = "regex" -version = "2023.10.3" +version = "2023.12.25" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.7" files = [ - {file = "regex-2023.10.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4c34d4f73ea738223a094d8e0ffd6d2c1a1b4c175da34d6b0de3d8d69bee6bcc"}, - {file = "regex-2023.10.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8f4e49fc3ce020f65411432183e6775f24e02dff617281094ba6ab079ef0915"}, - {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cd1bccf99d3ef1ab6ba835308ad85be040e6a11b0977ef7ea8c8005f01a3c29"}, - {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:81dce2ddc9f6e8f543d94b05d56e70d03a0774d32f6cca53e978dc01e4fc75b8"}, - {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c6b4d23c04831e3ab61717a707a5d763b300213db49ca680edf8bf13ab5d91b"}, - {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c15ad0aee158a15e17e0495e1e18741573d04eb6da06d8b84af726cfc1ed02ee"}, - {file = "regex-2023.10.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6239d4e2e0b52c8bd38c51b760cd870069f0bdf99700a62cd509d7a031749a55"}, - {file = "regex-2023.10.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4a8bf76e3182797c6b1afa5b822d1d5802ff30284abe4599e1247be4fd6b03be"}, - {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9c727bbcf0065cbb20f39d2b4f932f8fa1631c3e01fcedc979bd4f51fe051c5"}, - {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3ccf2716add72f80714b9a63899b67fa711b654be3fcdd34fa391d2d274ce767"}, - {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:107ac60d1bfdc3edb53be75e2a52aff7481b92817cfdddd9b4519ccf0e54a6ff"}, - {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:00ba3c9818e33f1fa974693fb55d24cdc8ebafcb2e4207680669d8f8d7cca79a"}, - {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f0a47efb1dbef13af9c9a54a94a0b814902e547b7f21acb29434504d18f36e3a"}, - {file = "regex-2023.10.3-cp310-cp310-win32.whl", hash = "sha256:36362386b813fa6c9146da6149a001b7bd063dabc4d49522a1f7aa65b725c7ec"}, - {file = "regex-2023.10.3-cp310-cp310-win_amd64.whl", hash = "sha256:c65a3b5330b54103e7d21cac3f6bf3900d46f6d50138d73343d9e5b2900b2353"}, - {file = "regex-2023.10.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:90a79bce019c442604662d17bf69df99090e24cdc6ad95b18b6725c2988a490e"}, - {file = "regex-2023.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c7964c2183c3e6cce3f497e3a9f49d182e969f2dc3aeeadfa18945ff7bdd7051"}, - {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ef80829117a8061f974b2fda8ec799717242353bff55f8a29411794d635d964"}, - {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5addc9d0209a9afca5fc070f93b726bf7003bd63a427f65ef797a931782e7edc"}, - {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c148bec483cc4b421562b4bcedb8e28a3b84fcc8f0aa4418e10898f3c2c0eb9b"}, - {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d1f21af4c1539051049796a0f50aa342f9a27cde57318f2fc41ed50b0dbc4ac"}, - {file = "regex-2023.10.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b9ac09853b2a3e0d0082104036579809679e7715671cfbf89d83c1cb2a30f58"}, - {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ebedc192abbc7fd13c5ee800e83a6df252bec691eb2c4bedc9f8b2e2903f5e2a"}, - {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d8a993c0a0ffd5f2d3bda23d0cd75e7086736f8f8268de8a82fbc4bd0ac6791e"}, - {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:be6b7b8d42d3090b6c80793524fa66c57ad7ee3fe9722b258aec6d0672543fd0"}, - {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4023e2efc35a30e66e938de5aef42b520c20e7eda7bb5fb12c35e5d09a4c43f6"}, - {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0d47840dc05e0ba04fe2e26f15126de7c755496d5a8aae4a08bda4dd8d646c54"}, - {file = "regex-2023.10.3-cp311-cp311-win32.whl", hash = "sha256:9145f092b5d1977ec8c0ab46e7b3381b2fd069957b9862a43bd383e5c01d18c2"}, - {file = "regex-2023.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:b6104f9a46bd8743e4f738afef69b153c4b8b592d35ae46db07fc28ae3d5fb7c"}, - {file = "regex-2023.10.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bff507ae210371d4b1fe316d03433ac099f184d570a1a611e541923f78f05037"}, - {file = "regex-2023.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be5e22bbb67924dea15039c3282fa4cc6cdfbe0cbbd1c0515f9223186fc2ec5f"}, - {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a992f702c9be9c72fa46f01ca6e18d131906a7180950958f766c2aa294d4b41"}, - {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7434a61b158be563c1362d9071358f8ab91b8d928728cd2882af060481244c9e"}, - {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2169b2dcabf4e608416f7f9468737583ce5f0a6e8677c4efbf795ce81109d7c"}, - {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9e908ef5889cda4de038892b9accc36d33d72fb3e12c747e2799a0e806ec841"}, - {file = "regex-2023.10.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12bd4bc2c632742c7ce20db48e0d99afdc05e03f0b4c1af90542e05b809a03d9"}, - {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bc72c231f5449d86d6c7d9cc7cd819b6eb30134bb770b8cfdc0765e48ef9c420"}, - {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bce8814b076f0ce5766dc87d5a056b0e9437b8e0cd351b9a6c4e1134a7dfbda9"}, - {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:ba7cd6dc4d585ea544c1412019921570ebd8a597fabf475acc4528210d7c4a6f"}, - {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b0c7d2f698e83f15228ba41c135501cfe7d5740181d5903e250e47f617eb4292"}, - {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5a8f91c64f390ecee09ff793319f30a0f32492e99f5dc1c72bc361f23ccd0a9a"}, - {file = "regex-2023.10.3-cp312-cp312-win32.whl", hash = "sha256:ad08a69728ff3c79866d729b095872afe1e0557251da4abb2c5faff15a91d19a"}, - {file = "regex-2023.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:39cdf8d141d6d44e8d5a12a8569d5a227f645c87df4f92179bd06e2e2705e76b"}, - {file = "regex-2023.10.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4a3ee019a9befe84fa3e917a2dd378807e423d013377a884c1970a3c2792d293"}, - {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76066d7ff61ba6bf3cb5efe2428fc82aac91802844c022d849a1f0f53820502d"}, - {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe50b61bab1b1ec260fa7cd91106fa9fece57e6beba05630afe27c71259c59b"}, - {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fd88f373cb71e6b59b7fa597e47e518282455c2734fd4306a05ca219a1991b0"}, - {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ab05a182c7937fb374f7e946f04fb23a0c0699c0450e9fb02ef567412d2fa3"}, - {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dac37cf08fcf2094159922edc7a2784cfcc5c70f8354469f79ed085f0328ebdf"}, - {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e54ddd0bb8fb626aa1f9ba7b36629564544954fff9669b15da3610c22b9a0991"}, - {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3367007ad1951fde612bf65b0dffc8fd681a4ab98ac86957d16491400d661302"}, - {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:16f8740eb6dbacc7113e3097b0a36065a02e37b47c936b551805d40340fb9971"}, - {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:f4f2ca6df64cbdd27f27b34f35adb640b5d2d77264228554e68deda54456eb11"}, - {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:39807cbcbe406efca2a233884e169d056c35aa7e9f343d4e78665246a332f597"}, - {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7eece6fbd3eae4a92d7c748ae825cbc1ee41a89bb1c3db05b5578ed3cfcfd7cb"}, - {file = "regex-2023.10.3-cp37-cp37m-win32.whl", hash = "sha256:ce615c92d90df8373d9e13acddd154152645c0dc060871abf6bd43809673d20a"}, - {file = "regex-2023.10.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0f649fa32fe734c4abdfd4edbb8381c74abf5f34bc0b3271ce687b23729299ed"}, - {file = "regex-2023.10.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b98b7681a9437262947f41c7fac567c7e1f6eddd94b0483596d320092004533"}, - {file = "regex-2023.10.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:91dc1d531f80c862441d7b66c4505cd6ea9d312f01fb2f4654f40c6fdf5cc37a"}, - {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82fcc1f1cc3ff1ab8a57ba619b149b907072e750815c5ba63e7aa2e1163384a4"}, - {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7979b834ec7a33aafae34a90aad9f914c41fd6eaa8474e66953f3f6f7cbd4368"}, - {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef71561f82a89af6cfcbee47f0fabfdb6e63788a9258e913955d89fdd96902ab"}, - {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd829712de97753367153ed84f2de752b86cd1f7a88b55a3a775eb52eafe8a94"}, - {file = "regex-2023.10.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00e871d83a45eee2f8688d7e6849609c2ca2a04a6d48fba3dff4deef35d14f07"}, - {file = "regex-2023.10.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:706e7b739fdd17cb89e1fbf712d9dc21311fc2333f6d435eac2d4ee81985098c"}, - {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cc3f1c053b73f20c7ad88b0d1d23be7e7b3901229ce89f5000a8399746a6e039"}, - {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6f85739e80d13644b981a88f529d79c5bdf646b460ba190bffcaf6d57b2a9863"}, - {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:741ba2f511cc9626b7561a440f87d658aabb3d6b744a86a3c025f866b4d19e7f"}, - {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e77c90ab5997e85901da85131fd36acd0ed2221368199b65f0d11bca44549711"}, - {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:979c24cbefaf2420c4e377ecd1f165ea08cc3d1fbb44bdc51bccbbf7c66a2cb4"}, - {file = "regex-2023.10.3-cp38-cp38-win32.whl", hash = "sha256:58837f9d221744d4c92d2cf7201c6acd19623b50c643b56992cbd2b745485d3d"}, - {file = "regex-2023.10.3-cp38-cp38-win_amd64.whl", hash = "sha256:c55853684fe08d4897c37dfc5faeff70607a5f1806c8be148f1695be4a63414b"}, - {file = "regex-2023.10.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2c54e23836650bdf2c18222c87f6f840d4943944146ca479858404fedeb9f9af"}, - {file = "regex-2023.10.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:69c0771ca5653c7d4b65203cbfc5e66db9375f1078689459fe196fe08b7b4930"}, - {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ac965a998e1388e6ff2e9781f499ad1eaa41e962a40d11c7823c9952c77123e"}, - {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c0e8fae5b27caa34177bdfa5a960c46ff2f78ee2d45c6db15ae3f64ecadde14"}, - {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c56c3d47da04f921b73ff9415fbaa939f684d47293f071aa9cbb13c94afc17d"}, - {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ef1e014eed78ab650bef9a6a9cbe50b052c0aebe553fb2881e0453717573f52"}, - {file = "regex-2023.10.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d29338556a59423d9ff7b6eb0cb89ead2b0875e08fe522f3e068b955c3e7b59b"}, - {file = "regex-2023.10.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9c6d0ced3c06d0f183b73d3c5920727268d2201aa0fe6d55c60d68c792ff3588"}, - {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:994645a46c6a740ee8ce8df7911d4aee458d9b1bc5639bc968226763d07f00fa"}, - {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:66e2fe786ef28da2b28e222c89502b2af984858091675044d93cb50e6f46d7af"}, - {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:11175910f62b2b8c055f2b089e0fedd694fe2be3941b3e2633653bc51064c528"}, - {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:06e9abc0e4c9ab4779c74ad99c3fc10d3967d03114449acc2c2762ad4472b8ca"}, - {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fb02e4257376ae25c6dd95a5aec377f9b18c09be6ebdefa7ad209b9137b73d48"}, - {file = "regex-2023.10.3-cp39-cp39-win32.whl", hash = "sha256:3b2c3502603fab52d7619b882c25a6850b766ebd1b18de3df23b2f939360e1bd"}, - {file = "regex-2023.10.3-cp39-cp39-win_amd64.whl", hash = "sha256:adbccd17dcaff65704c856bd29951c58a1bd4b2b0f8ad6b826dbd543fe740988"}, - {file = "regex-2023.10.3.tar.gz", hash = "sha256:3fef4f844d2290ee0ba57addcec17eec9e3df73f10a2748485dfd6a3a188cc0f"}, + {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"}, + {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"}, + {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"}, + {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"}, + {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"}, + {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"}, + {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"}, + {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"}, + {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"}, + {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"}, + {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"}, + {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"}, + {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"}, + {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"}, + {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"}, + {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"}, + {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"}, ] [[package]] @@ -2442,160 +2245,132 @@ six = "*" fixture = ["fixtures"] test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "testtools"] -[[package]] -name = "requirementslib" -version = "3.0.0" -description = "A tool for converting between pip-style and pipfile requirements." -optional = false -python-versions = ">=3.7" -files = [ - {file = "requirementslib-3.0.0-py2.py3-none-any.whl", hash = "sha256:67b42903d7c32f89c7047d1020c619d37cb515c475a4ae6f4e5683e1c56d7bf7"}, - {file = "requirementslib-3.0.0.tar.gz", hash = "sha256:28f8e0b1c38b34ae06de68ef115b03bbcdcdb99f9e9393333ff06ded443e3f24"}, -] - -[package.dependencies] -distlib = ">=0.2.8" -pep517 = ">=0.5.0" -pip = ">=23.1" -platformdirs = "*" -plette = {version = "*", extras = ["validation"]} -pydantic = "*" -requests = "*" -setuptools = ">=40.8" -tomlkit = ">=0.5.3" - -[package.extras] -dev = ["nox", "parver", "towncrier", "twine"] -docs = ["sphinx", "sphinx-rtd-theme"] -tests = ["coverage", "hypothesis", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "readme-renderer[md]"] - [[package]] name = "rlp" -version = "3.0.0" -description = "A package for Recursive Length Prefix encoding and decoding" +version = "4.0.0" +description = "rlp: A package for Recursive Length Prefix encoding and decoding" optional = false -python-versions = "*" +python-versions = ">=3.8, <4" files = [ - {file = "rlp-3.0.0-py2.py3-none-any.whl", hash = "sha256:d2a963225b3f26795c5b52310e0871df9824af56823d739511583ef459895a7d"}, - {file = "rlp-3.0.0.tar.gz", hash = "sha256:63b0465d2948cd9f01de449d7adfb92d207c1aef3982f20310f8009be4a507e8"}, + {file = "rlp-4.0.0-py3-none-any.whl", hash = "sha256:1747fd933e054e6d25abfe591be92e19a4193a56c93981c05bd0f84dfe279f14"}, + {file = "rlp-4.0.0.tar.gz", hash = "sha256:61a5541f86e4684ab145cb849a5929d2ced8222930a570b3941cf4af16b72a78"}, ] [package.dependencies] -eth-utils = ">=2.0.0,<3" +eth-utils = ">=2" [package.extras] -dev = ["Sphinx (>=1.6.5,<2)", "bumpversion (>=0.5.3,<1)", "flake8 (==3.4.1)", "hypothesis (==5.19.0)", "ipython", "pytest (>=6.2.5,<7)", "pytest-watch (>=4.1.0,<5)", "pytest-xdist", "setuptools (>=36.2.0)", "sphinx-rtd-theme (>=0.1.9)", "tox (>=2.9.1,<3)", "twine", "wheel"] -doc = ["Sphinx (>=1.6.5,<2)", "sphinx-rtd-theme (>=0.1.9)"] -lint = ["flake8 (==3.4.1)"] +dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "hypothesis (==5.19.0)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] rust-backend = ["rusty-rlp (>=0.2.1,<0.3)"] -test = ["hypothesis (==5.19.0)", "pytest (>=6.2.5,<7)", "tox (>=2.9.1,<3)"] +test = ["hypothesis (==5.19.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "rpds-py" -version = "0.13.2" +version = "0.17.1" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.13.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1ceebd0ae4f3e9b2b6b553b51971921853ae4eebf3f54086be0565d59291e53d"}, - {file = "rpds_py-0.13.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:46e1ed994a0920f350a4547a38471217eb86f57377e9314fbaaa329b71b7dfe3"}, - {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee353bb51f648924926ed05e0122b6a0b1ae709396a80eb583449d5d477fcdf7"}, - {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:530190eb0cd778363bbb7596612ded0bb9fef662daa98e9d92a0419ab27ae914"}, - {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d311e44dd16d2434d5506d57ef4d7036544fc3c25c14b6992ef41f541b10fb"}, - {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e72f750048b32d39e87fc85c225c50b2a6715034848dbb196bf3348aa761fa1"}, - {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db09b98c7540df69d4b47218da3fbd7cb466db0fb932e971c321f1c76f155266"}, - {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2ac26f50736324beb0282c819668328d53fc38543fa61eeea2c32ea8ea6eab8d"}, - {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:12ecf89bd54734c3c2c79898ae2021dca42750c7bcfb67f8fb3315453738ac8f"}, - {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a44c8440183b43167fd1a0819e8356692bf5db1ad14ce140dbd40a1485f2dea"}, - {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bcef4f2d3dc603150421de85c916da19471f24d838c3c62a4f04c1eb511642c1"}, - {file = "rpds_py-0.13.2-cp310-none-win32.whl", hash = "sha256:ee6faebb265e28920a6f23a7d4c362414b3f4bb30607141d718b991669e49ddc"}, - {file = "rpds_py-0.13.2-cp310-none-win_amd64.whl", hash = "sha256:ac96d67b37f28e4b6ecf507c3405f52a40658c0a806dffde624a8fcb0314d5fd"}, - {file = "rpds_py-0.13.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:b5f6328e8e2ae8238fc767703ab7b95785521c42bb2b8790984e3477d7fa71ad"}, - {file = "rpds_py-0.13.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:729408136ef8d45a28ee9a7411917c9e3459cf266c7e23c2f7d4bb8ef9e0da42"}, - {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65cfed9c807c27dee76407e8bb29e6f4e391e436774bcc769a037ff25ad8646e"}, - {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aefbdc934115d2f9278f153952003ac52cd2650e7313750390b334518c589568"}, - {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d48db29bd47814671afdd76c7652aefacc25cf96aad6daefa82d738ee87461e2"}, - {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3c55d7f2d817183d43220738270efd3ce4e7a7b7cbdaefa6d551ed3d6ed89190"}, - {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6aadae3042f8e6db3376d9e91f194c606c9a45273c170621d46128f35aef7cd0"}, - {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5feae2f9aa7270e2c071f488fab256d768e88e01b958f123a690f1cc3061a09c"}, - {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:51967a67ea0d7b9b5cd86036878e2d82c0b6183616961c26d825b8c994d4f2c8"}, - {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d0c10d803549427f427085ed7aebc39832f6e818a011dcd8785e9c6a1ba9b3e"}, - {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:603d5868f7419081d616dab7ac3cfa285296735e7350f7b1e4f548f6f953ee7d"}, - {file = "rpds_py-0.13.2-cp311-none-win32.whl", hash = "sha256:b8996ffb60c69f677245f5abdbcc623e9442bcc91ed81b6cd6187129ad1fa3e7"}, - {file = "rpds_py-0.13.2-cp311-none-win_amd64.whl", hash = "sha256:5379e49d7e80dca9811b36894493d1c1ecb4c57de05c36f5d0dd09982af20211"}, - {file = "rpds_py-0.13.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8a776a29b77fe0cc28fedfd87277b0d0f7aa930174b7e504d764e0b43a05f381"}, - {file = "rpds_py-0.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2a1472956c5bcc49fb0252b965239bffe801acc9394f8b7c1014ae9258e4572b"}, - {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f252dfb4852a527987a9156cbcae3022a30f86c9d26f4f17b8c967d7580d65d2"}, - {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f0d320e70b6b2300ff6029e234e79fe44e9dbbfc7b98597ba28e054bd6606a57"}, - {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ade2ccb937060c299ab0dfb2dea3d2ddf7e098ed63ee3d651ebfc2c8d1e8632a"}, - {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9d121be0217787a7d59a5c6195b0842d3f701007333426e5154bf72346aa658"}, - {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fa6bd071ec6d90f6e7baa66ae25820d57a8ab1b0a3c6d3edf1834d4b26fafa2"}, - {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c918621ee0a3d1fe61c313f2489464f2ae3d13633e60f520a8002a5e910982ee"}, - {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:25b28b3d33ec0a78e944aaaed7e5e2a94ac811bcd68b557ca48a0c30f87497d2"}, - {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:31e220a040b89a01505128c2f8a59ee74732f666439a03e65ccbf3824cdddae7"}, - {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:15253fff410873ebf3cfba1cc686a37711efcd9b8cb30ea21bb14a973e393f60"}, - {file = "rpds_py-0.13.2-cp312-none-win32.whl", hash = "sha256:b981a370f8f41c4024c170b42fbe9e691ae2dbc19d1d99151a69e2c84a0d194d"}, - {file = "rpds_py-0.13.2-cp312-none-win_amd64.whl", hash = "sha256:4c4e314d36d4f31236a545696a480aa04ea170a0b021e9a59ab1ed94d4c3ef27"}, - {file = "rpds_py-0.13.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:80e5acb81cb49fd9f2d5c08f8b74ffff14ee73b10ca88297ab4619e946bcb1e1"}, - {file = "rpds_py-0.13.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:efe093acc43e869348f6f2224df7f452eab63a2c60a6c6cd6b50fd35c4e075ba"}, - {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c2a61c0e4811012b0ba9f6cdcb4437865df5d29eab5d6018ba13cee1c3064a0"}, - {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:751758d9dd04d548ec679224cc00e3591f5ebf1ff159ed0d4aba6a0746352452"}, - {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ba8858933f0c1a979781272a5f65646fca8c18c93c99c6ddb5513ad96fa54b1"}, - {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bfdfbe6a36bc3059fff845d64c42f2644cf875c65f5005db54f90cdfdf1df815"}, - {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa0379c1935c44053c98826bc99ac95f3a5355675a297ac9ce0dfad0ce2d50ca"}, - {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5593855b5b2b73dd8413c3fdfa5d95b99d657658f947ba2c4318591e745d083"}, - {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2a7bef6977043673750a88da064fd513f89505111014b4e00fbdd13329cd4e9a"}, - {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:3ab96754d23372009638a402a1ed12a27711598dd49d8316a22597141962fe66"}, - {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:e06cfea0ece444571d24c18ed465bc93afb8c8d8d74422eb7026662f3d3f779b"}, - {file = "rpds_py-0.13.2-cp38-none-win32.whl", hash = "sha256:5493569f861fb7b05af6d048d00d773c6162415ae521b7010197c98810a14cab"}, - {file = "rpds_py-0.13.2-cp38-none-win_amd64.whl", hash = "sha256:b07501b720cf060c5856f7b5626e75b8e353b5f98b9b354a21eb4bfa47e421b1"}, - {file = "rpds_py-0.13.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:881df98f0a8404d32b6de0fd33e91c1b90ed1516a80d4d6dc69d414b8850474c"}, - {file = "rpds_py-0.13.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d79c159adea0f1f4617f54aa156568ac69968f9ef4d1e5fefffc0a180830308e"}, - {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38d4f822ee2f338febcc85aaa2547eb5ba31ba6ff68d10b8ec988929d23bb6b4"}, - {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5d75d6d220d55cdced2f32cc22f599475dbe881229aeddba6c79c2e9df35a2b3"}, - {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d97e9ae94fb96df1ee3cb09ca376c34e8a122f36927230f4c8a97f469994bff"}, - {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67a429520e97621a763cf9b3ba27574779c4e96e49a27ff8a1aa99ee70beb28a"}, - {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:188435794405c7f0573311747c85a96b63c954a5f2111b1df8018979eca0f2f0"}, - {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:38f9bf2ad754b4a45b8210a6c732fe876b8a14e14d5992a8c4b7c1ef78740f53"}, - {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a6ba2cb7d676e9415b9e9ac7e2aae401dc1b1e666943d1f7bc66223d3d73467b"}, - {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:eaffbd8814bb1b5dc3ea156a4c5928081ba50419f9175f4fc95269e040eff8f0"}, - {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a4c1058cdae6237d97af272b326e5f78ee7ee3bbffa6b24b09db4d828810468"}, - {file = "rpds_py-0.13.2-cp39-none-win32.whl", hash = "sha256:b5267feb19070bef34b8dea27e2b504ebd9d31748e3ecacb3a4101da6fcb255c"}, - {file = "rpds_py-0.13.2-cp39-none-win_amd64.whl", hash = "sha256:ddf23960cb42b69bce13045d5bc66f18c7d53774c66c13f24cf1b9c144ba3141"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:97163a1ab265a1073a6372eca9f4eeb9f8c6327457a0b22ddfc4a17dcd613e74"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:25ea41635d22b2eb6326f58e608550e55d01df51b8a580ea7e75396bafbb28e9"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d59d4d451ba77f08cb4cd9268dec07be5bc65f73666302dbb5061989b17198"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7c564c58cf8f248fe859a4f0fe501b050663f3d7fbc342172f259124fb59933"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61dbc1e01dc0c5875da2f7ae36d6e918dc1b8d2ce04e871793976594aad8a57a"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdb82eb60d31b0c033a8e8ee9f3fc7dfbaa042211131c29da29aea8531b4f18f"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d204957169f0b3511fb95395a9da7d4490fb361763a9f8b32b345a7fe119cb45"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c45008ca79bad237cbc03c72bc5205e8c6f66403773929b1b50f7d84ef9e4d07"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:79bf58c08f0756adba691d480b5a20e4ad23f33e1ae121584cf3a21717c36dfa"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e86593bf8637659e6a6ed58854b6c87ec4e9e45ee8a4adfd936831cef55c2d21"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d329896c40d9e1e5c7715c98529e4a188a1f2df51212fd65102b32465612b5dc"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4a5375c5fff13f209527cd886dc75394f040c7d1ecad0a2cb0627f13ebe78a12"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:06d218e4464d31301e943b65b2c6919318ea6f69703a351961e1baaf60347276"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1f41d32a2ddc5a94df4b829b395916a4b7f103350fa76ba6de625fcb9e773ac"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6bc568b05e02cd612be53900c88aaa55012e744930ba2eeb56279db4c6676eb3"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d94d78418203904730585efa71002286ac4c8ac0689d0eb61e3c465f9e608ff"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bed0252c85e21cf73d2d033643c945b460d6a02fc4a7d644e3b2d6f5f2956c64"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:244e173bb6d8f3b2f0c4d7370a1aa341f35da3e57ffd1798e5b2917b91731fd3"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7f55cd9cf1564b7b03f238e4c017ca4794c05b01a783e9291065cb2858d86ce4"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:f03a1b3a4c03e3e0161642ac5367f08479ab29972ea0ffcd4fa18f729cd2be0a"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:f5f4424cb87a20b016bfdc157ff48757b89d2cc426256961643d443c6c277007"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c82bbf7e03748417c3a88c1b0b291288ce3e4887a795a3addaa7a1cfd9e7153e"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c0095b8aa3e432e32d372e9a7737e65b58d5ed23b9620fea7cb81f17672f1fa1"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:4c2d26aa03d877c9730bf005621c92da263523a1e99247590abbbe252ccb7824"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96f2975fb14f39c5fe75203f33dd3010fe37d1c4e33177feef1107b5ced750e3"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4dcc5ee1d0275cb78d443fdebd0241e58772a354a6d518b1d7af1580bbd2c4e8"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61d42d2b08430854485135504f672c14d4fc644dd243a9c17e7c4e0faf5ed07e"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d3a61e928feddc458a55110f42f626a2a20bea942ccedb6fb4cee70b4830ed41"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7de12b69d95072394998c622cfd7e8cea8f560db5fca6a62a148f902a1029f8b"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:87a90f5545fd61f6964e65eebde4dc3fa8660bb7d87adb01d4cf17e0a2b484ad"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:9c95a1a290f9acf7a8f2ebbdd183e99215d491beea52d61aa2a7a7d2c618ddc6"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:35f53c76a712e323c779ca39b9a81b13f219a8e3bc15f106ed1e1462d56fcfe9"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:96fb0899bb2ab353f42e5374c8f0789f54e0a94ef2f02b9ac7149c56622eaf31"}, - {file = "rpds_py-0.13.2.tar.gz", hash = "sha256:f8eae66a1304de7368932b42d801c67969fd090ddb1a7a24f27b435ed4bed68f"}, + {file = "rpds_py-0.17.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4128980a14ed805e1b91a7ed551250282a8ddf8201a4e9f8f5b7e6225f54170d"}, + {file = "rpds_py-0.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ff1dcb8e8bc2261a088821b2595ef031c91d499a0c1b031c152d43fe0a6ecec8"}, + {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d65e6b4f1443048eb7e833c2accb4fa7ee67cc7d54f31b4f0555b474758bee55"}, + {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a71169d505af63bb4d20d23a8fbd4c6ce272e7bce6cc31f617152aa784436f29"}, + {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:436474f17733c7dca0fbf096d36ae65277e8645039df12a0fa52445ca494729d"}, + {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10162fe3f5f47c37ebf6d8ff5a2368508fe22007e3077bf25b9c7d803454d921"}, + {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:720215373a280f78a1814becb1312d4e4d1077b1202a56d2b0815e95ccb99ce9"}, + {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70fcc6c2906cfa5c6a552ba7ae2ce64b6c32f437d8f3f8eea49925b278a61453"}, + {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:91e5a8200e65aaac342a791272c564dffcf1281abd635d304d6c4e6b495f29dc"}, + {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:99f567dae93e10be2daaa896e07513dd4bf9c2ecf0576e0533ac36ba3b1d5394"}, + {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24e4900a6643f87058a27320f81336d527ccfe503984528edde4bb660c8c8d59"}, + {file = "rpds_py-0.17.1-cp310-none-win32.whl", hash = "sha256:0bfb09bf41fe7c51413f563373e5f537eaa653d7adc4830399d4e9bdc199959d"}, + {file = "rpds_py-0.17.1-cp310-none-win_amd64.whl", hash = "sha256:20de7b7179e2031a04042e85dc463a93a82bc177eeba5ddd13ff746325558aa6"}, + {file = "rpds_py-0.17.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:65dcf105c1943cba45d19207ef51b8bc46d232a381e94dd38719d52d3980015b"}, + {file = "rpds_py-0.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:01f58a7306b64e0a4fe042047dd2b7d411ee82e54240284bab63e325762c1147"}, + {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:071bc28c589b86bc6351a339114fb7a029f5cddbaca34103aa573eba7b482382"}, + {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae35e8e6801c5ab071b992cb2da958eee76340e6926ec693b5ff7d6381441745"}, + {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149c5cd24f729e3567b56e1795f74577aa3126c14c11e457bec1b1c90d212e38"}, + {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e796051f2070f47230c745d0a77a91088fbee2cc0502e9b796b9c6471983718c"}, + {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e820ee1004327609b28db8307acc27f5f2e9a0b185b2064c5f23e815f248f8"}, + {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1957a2ab607f9added64478a6982742eb29f109d89d065fa44e01691a20fc20a"}, + {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8587fd64c2a91c33cdc39d0cebdaf30e79491cc029a37fcd458ba863f8815383"}, + {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4dc889a9d8a34758d0fcc9ac86adb97bab3fb7f0c4d29794357eb147536483fd"}, + {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2953937f83820376b5979318840f3ee47477d94c17b940fe31d9458d79ae7eea"}, + {file = "rpds_py-0.17.1-cp311-none-win32.whl", hash = "sha256:1bfcad3109c1e5ba3cbe2f421614e70439f72897515a96c462ea657261b96518"}, + {file = "rpds_py-0.17.1-cp311-none-win_amd64.whl", hash = "sha256:99da0a4686ada4ed0f778120a0ea8d066de1a0a92ab0d13ae68492a437db78bf"}, + {file = "rpds_py-0.17.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1dc29db3900cb1bb40353772417800f29c3d078dbc8024fd64655a04ee3c4bdf"}, + {file = "rpds_py-0.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82ada4a8ed9e82e443fcef87e22a3eed3654dd3adf6e3b3a0deb70f03e86142a"}, + {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d36b2b59e8cc6e576f8f7b671e32f2ff43153f0ad6d0201250a7c07f25d570e"}, + {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3677fcca7fb728c86a78660c7fb1b07b69b281964673f486ae72860e13f512ad"}, + {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:516fb8c77805159e97a689e2f1c80655c7658f5af601c34ffdb916605598cda2"}, + {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df3b6f45ba4515632c5064e35ca7f31d51d13d1479673185ba8f9fefbbed58b9"}, + {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a967dd6afda7715d911c25a6ba1517975acd8d1092b2f326718725461a3d33f9"}, + {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dbbb95e6fc91ea3102505d111b327004d1c4ce98d56a4a02e82cd451f9f57140"}, + {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02866e060219514940342a1f84303a1ef7a1dad0ac311792fbbe19b521b489d2"}, + {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2528ff96d09f12e638695f3a2e0c609c7b84c6df7c5ae9bfeb9252b6fa686253"}, + {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd345a13ce06e94c753dab52f8e71e5252aec1e4f8022d24d56decd31e1b9b23"}, + {file = "rpds_py-0.17.1-cp312-none-win32.whl", hash = "sha256:2a792b2e1d3038daa83fa474d559acfd6dc1e3650ee93b2662ddc17dbff20ad1"}, + {file = "rpds_py-0.17.1-cp312-none-win_amd64.whl", hash = "sha256:292f7344a3301802e7c25c53792fae7d1593cb0e50964e7bcdcc5cf533d634e3"}, + {file = "rpds_py-0.17.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:8ffe53e1d8ef2520ebcf0c9fec15bb721da59e8ef283b6ff3079613b1e30513d"}, + {file = "rpds_py-0.17.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4341bd7579611cf50e7b20bb8c2e23512a3dc79de987a1f411cb458ab670eb90"}, + {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4eb548daf4836e3b2c662033bfbfc551db58d30fd8fe660314f86bf8510b93"}, + {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b686f25377f9c006acbac63f61614416a6317133ab7fafe5de5f7dc8a06d42eb"}, + {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e21b76075c01d65d0f0f34302b5a7457d95721d5e0667aea65e5bb3ab415c25"}, + {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b86b21b348f7e5485fae740d845c65a880f5d1eda1e063bc59bef92d1f7d0c55"}, + {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f175e95a197f6a4059b50757a3dca33b32b61691bdbd22c29e8a8d21d3914cae"}, + {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1701fc54460ae2e5efc1dd6350eafd7a760f516df8dbe51d4a1c79d69472fbd4"}, + {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9051e3d2af8f55b42061603e29e744724cb5f65b128a491446cc029b3e2ea896"}, + {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:7450dbd659fed6dd41d1a7d47ed767e893ba402af8ae664c157c255ec6067fde"}, + {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5a024fa96d541fd7edaa0e9d904601c6445e95a729a2900c5aec6555fe921ed6"}, + {file = "rpds_py-0.17.1-cp38-none-win32.whl", hash = "sha256:da1ead63368c04a9bded7904757dfcae01eba0e0f9bc41d3d7f57ebf1c04015a"}, + {file = "rpds_py-0.17.1-cp38-none-win_amd64.whl", hash = "sha256:841320e1841bb53fada91c9725e766bb25009cfd4144e92298db296fb6c894fb"}, + {file = "rpds_py-0.17.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:f6c43b6f97209e370124baf2bf40bb1e8edc25311a158867eb1c3a5d449ebc7a"}, + {file = "rpds_py-0.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7d63ec01fe7c76c2dbb7e972fece45acbb8836e72682bde138e7e039906e2c"}, + {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81038ff87a4e04c22e1d81f947c6ac46f122e0c80460b9006e6517c4d842a6ec"}, + {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:810685321f4a304b2b55577c915bece4c4a06dfe38f6e62d9cc1d6ca8ee86b99"}, + {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25f071737dae674ca8937a73d0f43f5a52e92c2d178330b4c0bb6ab05586ffa6"}, + {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa5bfb13f1e89151ade0eb812f7b0d7a4d643406caaad65ce1cbabe0a66d695f"}, + {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfe07308b311a8293a0d5ef4e61411c5c20f682db6b5e73de6c7c8824272c256"}, + {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a000133a90eea274a6f28adc3084643263b1e7c1a5a66eb0a0a7a36aa757ed74"}, + {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d0e8a6434a3fbf77d11448c9c25b2f25244226cfbec1a5159947cac5b8c5fa4"}, + {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:efa767c220d94aa4ac3a6dd3aeb986e9f229eaf5bce92d8b1b3018d06bed3772"}, + {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:dbc56680ecf585a384fbd93cd42bc82668b77cb525343170a2d86dafaed2a84b"}, + {file = "rpds_py-0.17.1-cp39-none-win32.whl", hash = "sha256:270987bc22e7e5a962b1094953ae901395e8c1e1e83ad016c5cfcfff75a15a3f"}, + {file = "rpds_py-0.17.1-cp39-none-win_amd64.whl", hash = "sha256:2a7b2f2f56a16a6d62e55354dd329d929560442bd92e87397b7a9586a32e3e76"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a3264e3e858de4fc601741498215835ff324ff2482fd4e4af61b46512dd7fc83"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f2f3b28b40fddcb6c1f1f6c88c6f3769cd933fa493ceb79da45968a21dccc920"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9584f8f52010295a4a417221861df9bea4c72d9632562b6e59b3c7b87a1522b7"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c64602e8be701c6cfe42064b71c84ce62ce66ddc6422c15463fd8127db3d8066"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:060f412230d5f19fc8c8b75f315931b408d8ebf56aec33ef4168d1b9e54200b1"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9412abdf0ba70faa6e2ee6c0cc62a8defb772e78860cef419865917d86c7342"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9737bdaa0ad33d34c0efc718741abaafce62fadae72c8b251df9b0c823c63b22"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9f0e4dc0f17dcea4ab9d13ac5c666b6b5337042b4d8f27e01b70fae41dd65c57"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1db228102ab9d1ff4c64148c96320d0be7044fa28bd865a9ce628ce98da5973d"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:d8bbd8e56f3ba25a7d0cf980fc42b34028848a53a0e36c9918550e0280b9d0b6"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:be22ae34d68544df293152b7e50895ba70d2a833ad9566932d750d3625918b82"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bf046179d011e6114daf12a534d874958b039342b347348a78b7cdf0dd9d6041"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:1a746a6d49665058a5896000e8d9d2f1a6acba8a03b389c1e4c06e11e0b7f40d"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0b8bf5b8db49d8fd40f54772a1dcf262e8be0ad2ab0206b5a2ec109c176c0a4"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f7f4cb1f173385e8a39c29510dd11a78bf44e360fb75610594973f5ea141028b"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7fbd70cb8b54fe745301921b0816c08b6d917593429dfc437fd024b5ba713c58"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bdf1303df671179eaf2cb41e8515a07fc78d9d00f111eadbe3e14262f59c3d0"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad059a4bd14c45776600d223ec194e77db6c20255578bb5bcdd7c18fd169361"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3664d126d3388a887db44c2e293f87d500c4184ec43d5d14d2d2babdb4c64cad"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:698ea95a60c8b16b58be9d854c9f993c639f5c214cf9ba782eca53a8789d6b19"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:c3d2010656999b63e628a3c694f23020322b4178c450dc478558a2b6ef3cb9bb"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:938eab7323a736533f015e6069a7d53ef2dcc841e4e533b782c2bfb9fb12d84b"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1e626b365293a2142a62b9a614e1f8e331b28f3ca57b9f05ebbf4cf2a0f0bdc5"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:380e0df2e9d5d5d339803cfc6d183a5442ad7ab3c63c2a0982e8c824566c5ccc"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b760a56e080a826c2e5af09002c1a037382ed21d03134eb6294812dda268c811"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5576ee2f3a309d2bb403ec292d5958ce03953b0e57a11d224c1f134feaf8c40f"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3c3461ebb4c4f1bbc70b15d20b565759f97a5aaf13af811fcefc892e9197ba"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:637b802f3f069a64436d432117a7e58fab414b4e27a7e81049817ae94de45d8d"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffee088ea9b593cc6160518ba9bd319b5475e5f3e578e4552d63818773c6f56a"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ac732390d529d8469b831949c78085b034bff67f584559340008d0f6041a049"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:93432e747fb07fa567ad9cc7aaadd6e29710e515aabf939dfbed8046041346c6"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7b7d9ca34542099b4e185b3c2a2b2eda2e318a7dbde0b0d83357a6d4421b5296"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:0387ce69ba06e43df54e43968090f3626e231e4bc9150e4c3246947567695f68"}, + {file = "rpds_py-0.17.1.tar.gz", hash = "sha256:0210b2668f24c078307260bf88bdac9d6f1093635df5123789bfee4d8d7fc8e7"}, ] [[package]] @@ -2610,13 +2385,13 @@ files = [ [[package]] name = "setuptools" -version = "69.0.2" +version = "69.0.3" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"}, - {file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"}, + {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, + {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, ] [package.extras] @@ -2657,26 +2432,15 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -[[package]] -name = "tomlkit" -version = "0.12.3" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomlkit-0.12.3-py3-none-any.whl", hash = "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba"}, - {file = "tomlkit-0.12.3.tar.gz", hash = "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4"}, -] - [[package]] name = "toolz" -version = "0.12.0" +version = "0.12.1" description = "List processing tools and functional utilities" optional = false -python-versions = ">=3.5" +python-versions = ">=3.7" files = [ - {file = "toolz-0.12.0-py3-none-any.whl", hash = "sha256:2059bd4148deb1884bb0eb770a3cde70e7f954cfbbdc2285f1f2de01fd21eb6f"}, - {file = "toolz-0.12.0.tar.gz", hash = "sha256:88c570861c440ee3f2f6037c4654613228ff40c93a6c25e0eba70d17282c6194"}, + {file = "toolz-0.12.1-py3-none-any.whl", hash = "sha256:d22731364c07d72eea0a0ad45bafb2c2937ab6fd38a3507bf55eae8744aa7d85"}, + {file = "toolz-0.12.1.tar.gz", hash = "sha256:ecca342664893f177a13dac0e6b41cbd8ac25a358e5f215316d43e2100224f4d"}, ] [[package]] @@ -2728,13 +2492,13 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "web3" -version = "6.11.4" +version = "6.15.1" description = "web3.py" optional = false python-versions = ">=3.7.2" files = [ - {file = "web3-6.11.4-py3-none-any.whl", hash = "sha256:b63d461c6d48e9ec12ed22c293c1d22ef83d1ec650c570e70fc24a6432b1b4a3"}, - {file = "web3-6.11.4.tar.gz", hash = "sha256:5bf785e63868c271ebee05a9ab257858630a0b105d34872cfe6a6049a887fec6"}, + {file = "web3-6.15.1-py3-none-any.whl", hash = "sha256:4e4a8313aa4556ecde61c852a62405b853b667498b07da6ff05c29fe8c79096b"}, + {file = "web3-6.15.1.tar.gz", hash = "sha256:f9e7eefc1b3c3d194868a4ef9583b625c18ea3f31a48ebe143183db74898f381"}, ] [package.dependencies] @@ -2755,11 +2519,11 @@ typing-extensions = ">=4.0.1" websockets = ">=10.0.0" [package.extras] -dev = ["black (>=22.1.0)", "build (>=0.9.0)", "bumpversion", "eth-tester[py-evm] (==v0.9.1-b.1)", "flake8 (==3.8.3)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "importlib-metadata (<5.0)", "ipfshttpclient (==0.8.0a2)", "isort (>=5.11.0)", "mypy (==1.4.1)", "py-geth (>=3.11.0)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.18.1)", "pytest-mock (>=1.10)", "pytest-watch (>=4.2)", "pytest-xdist (>=1.29)", "setuptools (>=38.6.0)", "sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=3.18.0)", "tqdm (>4.32)", "twine (>=1.13)", "types-protobuf (==3.19.13)", "types-requests (>=2.26.1)", "types-setuptools (>=57.4.4)", "when-changed (>=0.3.0)"] +dev = ["black (>=22.1.0)", "build (>=0.9.0)", "bumpversion", "eth-tester[py-evm] (==v0.9.1-b.2)", "flake8 (==3.8.3)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "importlib-metadata (<5.0)", "ipfshttpclient (==0.8.0a2)", "isort (>=5.11.0)", "mypy (==1.4.1)", "py-geth (>=3.14.0)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.18.1,<0.23)", "pytest-mock (>=1.10)", "pytest-watch (>=4.2)", "pytest-xdist (>=1.29)", "setuptools (>=38.6.0)", "sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=3.18.0)", "tqdm (>4.32)", "twine (>=1.13)", "types-protobuf (==3.19.13)", "types-requests (>=2.26.1)", "types-setuptools (>=57.4.4)", "when-changed (>=0.3.0)"] docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] ipfs = ["ipfshttpclient (==0.8.0a2)"] linter = ["black (>=22.1.0)", "flake8 (==3.8.3)", "isort (>=5.11.0)", "mypy (==1.4.1)", "types-protobuf (==3.19.13)", "types-requests (>=2.26.1)", "types-setuptools (>=57.4.4)"] -tester = ["eth-tester[py-evm] (==v0.9.1-b.1)", "py-geth (>=3.11.0)"] +tester = ["eth-tester[py-evm] (==v0.9.1-b.2)", "py-geth (>=3.14.0)"] [[package]] name = "websockets" @@ -2842,20 +2606,6 @@ files = [ {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, ] -[[package]] -name = "yarg" -version = "0.1.9" -description = "A semi hard Cornish cheese, also queries PyPI (PyPI client)" -optional = false -python-versions = "*" -files = [ - {file = "yarg-0.1.9-py2.py3-none-any.whl", hash = "sha256:4f9cebdc00fac946c9bf2783d634e538a71c7d280a4d806d45fd4dc0ef441492"}, - {file = "yarg-0.1.9.tar.gz", hash = "sha256:55695bf4d1e3e7f756496c36a69ba32c40d18f821e38f61d028f6049e5e15911"}, -] - -[package.dependencies] -requests = "*" - [[package]] name = "yarl" version = "1.9.4" @@ -2962,4 +2712,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "5f05b8a2490ff9d4f5d2e82bb11fc71b8f8f50eb9618600bf8b28c85fe3b83bd" +content-hash = "9e0468421485c45e3ce0e68578905dac1e50a1ed1cae8f8c6a19c91b67f36ca0" diff --git a/pyinjective/denoms_devnet.ini b/pyinjective/denoms_devnet.ini index 62979d72..3c422179 100644 --- a/pyinjective/denoms_devnet.ini +++ b/pyinjective/denoms_devnet.ini @@ -169,6 +169,15 @@ min_display_price_tick_size = 0.001 min_quantity_tick_size = 10000000000000 min_display_quantity_tick_size = 0.00001 +[0x2d3b8d8833dda54a717adea9119134556848105fd6028e9a4a526e4e5a122a57] +description = 'Devnet Spot KIRA/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000 +min_display_quantity_tick_size = 1000 + [0x1422a13427d5eabd4d8de7907c8340f7e58cb15553a9fd4ad5c90406561886f9] description = 'Devnet Derivative COMP/USDT PERP' base = 0 @@ -291,6 +300,10 @@ decimals = 18 peggy_denom = inj decimals = 18 +[KIRA] +peggy_denom = factory/inj1xy3kvlr4q4wdd6lrelsrw2fk2ged0any44hhwq/KIRA +decimals = 6 + [LINK] peggy_denom = peggy0x514910771AF9Ca656af840dff83E8264EcF986CA decimals = 18 diff --git a/pyinjective/denoms_mainnet.ini b/pyinjective/denoms_mainnet.ini index b2430837..9d88ca6d 100644 --- a/pyinjective/denoms_mainnet.ini +++ b/pyinjective/denoms_mainnet.ini @@ -682,6 +682,24 @@ min_display_price_tick_size = 0.000001 min_quantity_tick_size = 10000000000000000000 min_display_quantity_tick_size = 10 +[0x0a1366c8b05658c0ccca6064e4b20aacd5ad350c02debd6ec0f4dc9178145d14] +description = 'Mainnet Spot GYEN/USDT' +base = 6 +quote = 6 +min_price_tick_size = 0.000001 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 100000000 +min_display_quantity_tick_size = 100 + +[0x9c8a91a894f773792b1e8d0b6a8224a6b748753738e9945020ee566266f817be] +description = 'Mainnet Spot USDCnb/USDT' +base = 6 +quote = 6 +min_price_tick_size = 0.0001 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 100000 +min_display_quantity_tick_size = 0.1 + [0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce] description = 'Mainnet Derivative BTC/USDT PERP' base = 0 @@ -736,14 +754,23 @@ min_display_price_tick_size = 0.001 min_quantity_tick_size = 0.01 min_display_quantity_tick_size = 0.01 +[0xcf18525b53e54ad7d27477426ade06d69d8d56d2f3bf35fe5ce2ad9eb97c2fbc] +description = 'Mainnet Derivative OSMO/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + [0x06c5a306492ddc2b8dc56969766959163287ed68a6b59baa2f42330dda0aebe0] description = 'Mainnet Derivative SOL/USDT PERP' base = 0 quote = 6 min_price_tick_size = 10000 min_display_price_tick_size = 0.01 -min_quantity_tick_size = 0.1 -min_display_quantity_tick_size = 0.1 +min_quantity_tick_size = 0.001 +min_display_quantity_tick_size = 0.001 [0xcd0c859a99f26bb3530e21890937ed77d20754aa7825a599c71710514fc125ef] description = 'Mainnet Derivative 1MPEPE/USDT PERP' @@ -817,6 +844,51 @@ min_display_price_tick_size = 0.00001 min_quantity_tick_size = 1 min_display_quantity_tick_size = 1 +[0x30a1463cfb4c393c80e257ab93118cecd73c1e632dc4d2d31c12a51bc0a70bd7] +description = 'Mainnet Derivative AVAX/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.01 +min_quantity_tick_size = 0.01 +min_display_quantity_tick_size = 0.01 + +[0x18b2ca44b3d20a3b87c87d3765669b09b73b5e900693896c08394c70e79ab1e7] +description = 'Mainnet Derivative SUI/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + +[0x1a6d3a59f45904e0a4a2eed269fc2f552e7e407ac90aaaeb602c31b017573f88] +description = 'Mainnet Derivative WIF/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 100 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1 +min_display_quantity_tick_size = 1 + +[0x48fcecd66ebabbf5a331178ec693b261dfae66ddfe6f552d7446744c6e78046c] +description = 'Mainnet Derivative OP/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + +[0x6ddf0b8fbbd888981aafdae9fc967a12c6777aac4dd100a8257b8755c0c4b7d5] +description = 'Mainnet Derivative ARB/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + [AAVE] peggy_denom = peggy0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9 decimals = 18 @@ -845,6 +917,10 @@ decimals = 6 peggy_denom = peggy0xBB0E17EF65F82Ab018d8EDd776e8DD940327B28b decimals = 18 +[Axelar Wrapped USDC] +peggy_denom = ibc/7E1AF94AD246BE522892751046F0C959B768642E5671CC3742264068D49553C0 +decimals = 6 + [BRETT] peggy_denom = factory/inj13jjdsa953w03dvecsr43dj5r6a2vzt7n0spncv/brett decimals = 6 @@ -885,6 +961,10 @@ decimals = 6 peggy_denom = peggy0xc944E90C64B2c07662A292be6244BDf05Cda44a7 decimals = 18 +[GYEN] +peggy_denom = peggy0xC08512927D12348F6620a698105e1BAac6EcD911 +decimals = 6 + [HUAHUA] peggy_denom = ibc/E7807A46C0B7B44B350DA58F51F278881B863EC4DCA94635DAB39E52C30766CB decimals = 6 @@ -933,6 +1013,10 @@ decimals = 18 peggy_denom = factory/inj1xtel2knkt8hmc9dnzpjz6kdmacgcfmlv5f308w/ninja decimals = 6 +[Noble USD Coin] +peggy_denom = ibc/2CBC2EA121AE42563B08028466F37B600F2D7D4282342DE938283CC3FB2BC00E +decimals = 6 + [ORAI] peggy_denom = ibc/C20C0A822BD22B2CEF0D067400FCCFB6FAEEE9E91D360B4E0725BD522302D565 decimals = 6 @@ -973,14 +1057,6 @@ decimals = 6 peggy_denom = peggy0x6B3595068778DD592e39A122f4f5a5cF09C90fE2 decimals = 18 -[SteadyBTC] -peggy_denom = peggy0x4986fD36b6b16f49b43282Ee2e24C5cF90ed166d -decimals = 18 - -[SteadyETH] -peggy_denom = peggy0x3F07A84eCdf494310D397d24c1C78B041D2fa622 -decimals = 18 - [TALIS] peggy_denom = factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis decimals = 6 @@ -997,12 +1073,12 @@ decimals = 18 peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj1q6zlut7gtkzknkk773jecujwsdkgq882akqksk decimals = 6 -[USDC] -peggy_denom = peggy0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 +[USD Coin (Wormhole from Solana)] +peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj12pwnhtv7yat2s30xuf4gdk9qm85v4j3e60dgvu decimals = 6 -[USDCso] -peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj12pwnhtv7yat2s30xuf4gdk9qm85v4j3e60dgvu +[USDC] +peggy_denom = peggy0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 decimals = 6 [USDT] @@ -1049,10 +1125,6 @@ decimals = 6 peggy_denom = peggy0xb2617246d0c6c0087f18703d576831899ca94f01 decimals = 18 -[axlUSDC] -peggy_denom = ibc/7E1AF94AD246BE522892751046F0C959B768642E5671CC3742264068D49553C0 -decimals = 6 - [nINJ] peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj13xlpypcwl5fuc84uhqzzqumnrcfpptyl6w3vrf decimals = 18 @@ -1060,3 +1132,11 @@ decimals = 18 [stINJ] peggy_denom = ibc/AC87717EA002B0123B10A05063E69BCA274BA2C44D842AEEB41558D2856DCE93 decimals = 18 + +[steadyBTC] +peggy_denom = peggy0x4986fD36b6b16f49b43282Ee2e24C5cF90ed166d +decimals = 18 + +[steadyETH] +peggy_denom = peggy0x3F07A84eCdf494310D397d24c1C78B041D2fa622 +decimals = 18 diff --git a/pyinjective/denoms_testnet.ini b/pyinjective/denoms_testnet.ini index d81212d8..fd823592 100644 --- a/pyinjective/denoms_testnet.ini +++ b/pyinjective/denoms_testnet.ini @@ -397,7 +397,7 @@ decimals = 8 peggy_denom = inj decimals = 18 -[MITOTEST1] +[MitoTest1] peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/mitotest1 decimals = 18 diff --git a/pyproject.toml b/pyproject.toml index a1fdb3ba..cfea69b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,6 @@ include = [ [tool.poetry.dependencies] python = "^3.9" aiohttp = "*" -asyncio = "*" bech32 = "*" bip32 = "*" coincurve = "*" @@ -41,7 +40,7 @@ websockets = "*" web3 = "^6.0" [tool.poetry.group.test.dependencies] -pytest = "*" +pytest = "<8" pytest-asyncio = "*" pytest-grpc = "*" requests-mock = "*" @@ -53,6 +52,7 @@ pre-commit = "^3.4.0" flakeheaven = "^3.3.0" isort = "^5.12.0" black = "^23.9.1" +python-dotenv = "^1.0.1" [tool.flakeheaven] From 33e29622943f0ed87f6b3dde3aca0f9c690ea8b8 Mon Sep 17 00:00:00 2001 From: abel Date: Fri, 9 Feb 2024 00:14:58 -0300 Subject: [PATCH 06/44] (feat) Added support for all `distribution` module queries. Added also new example scripts for all queries and unit tests --- .../1_ValidatorDistributionInfo.py | 16 + .../2_ValidatorOutstandingRewards.py | 16 + .../distribution/3_ValidatorCommission.py | 16 + .../distribution/4_ValidatorSlashes.py | 20 ++ .../distribution/5_DelegationRewards.py | 19 + .../distribution/6_DelegationTotalRewards.py | 18 + .../distribution/7_DelegatorValidators.py | 18 + .../8_DelegatorWithdrawAddress.py | 18 + .../distribution/9_CommunityPool.py | 15 + pyinjective/async_client.py | 67 ++++ .../chain/grpc/chain_grpc_distribution_api.py | 109 ++++++ ...y => configurable_authz_query_servicer.py} | 0 ...onfigurable_distribution_query_servicer.py | 69 ++++ .../grpc/test_chain_grpc_distribution_api.py | 338 ++++++++++++++++++ 14 files changed, 739 insertions(+) create mode 100644 examples/chain_client/distribution/1_ValidatorDistributionInfo.py create mode 100644 examples/chain_client/distribution/2_ValidatorOutstandingRewards.py create mode 100644 examples/chain_client/distribution/3_ValidatorCommission.py create mode 100644 examples/chain_client/distribution/4_ValidatorSlashes.py create mode 100644 examples/chain_client/distribution/5_DelegationRewards.py create mode 100644 examples/chain_client/distribution/6_DelegationTotalRewards.py create mode 100644 examples/chain_client/distribution/7_DelegatorValidators.py create mode 100644 examples/chain_client/distribution/8_DelegatorWithdrawAddress.py create mode 100644 examples/chain_client/distribution/9_CommunityPool.py create mode 100644 pyinjective/client/chain/grpc/chain_grpc_distribution_api.py rename tests/client/chain/grpc/{configurable_autz_query_servicer.py => configurable_authz_query_servicer.py} (100%) create mode 100644 tests/client/chain/grpc/configurable_distribution_query_servicer.py create mode 100644 tests/client/chain/grpc/test_chain_grpc_distribution_api.py diff --git a/examples/chain_client/distribution/1_ValidatorDistributionInfo.py b/examples/chain_client/distribution/1_ValidatorDistributionInfo.py new file mode 100644 index 00000000..13161630 --- /dev/null +++ b/examples/chain_client/distribution/1_ValidatorDistributionInfo.py @@ -0,0 +1,16 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + distribution_info = await client.fetch_validator_distribution_info(validator_address=validator_address) + print(distribution_info) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/2_ValidatorOutstandingRewards.py b/examples/chain_client/distribution/2_ValidatorOutstandingRewards.py new file mode 100644 index 00000000..31833682 --- /dev/null +++ b/examples/chain_client/distribution/2_ValidatorOutstandingRewards.py @@ -0,0 +1,16 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + rewards = await client.fetch_validator_outstanding_rewards(validator_address=validator_address) + print(rewards) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/3_ValidatorCommission.py b/examples/chain_client/distribution/3_ValidatorCommission.py new file mode 100644 index 00000000..a82e191b --- /dev/null +++ b/examples/chain_client/distribution/3_ValidatorCommission.py @@ -0,0 +1,16 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + commission = await client.fetch_validator_commission(validator_address=validator_address) + print(commission) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/4_ValidatorSlashes.py b/examples/chain_client/distribution/4_ValidatorSlashes.py new file mode 100644 index 00000000..08dbfea1 --- /dev/null +++ b/examples/chain_client/distribution/4_ValidatorSlashes.py @@ -0,0 +1,20 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + limit = 2 + pagination = PaginationOption(limit=limit) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + contracts = await client.fetch_validator_slashes(validator_address=validator_address, pagination=pagination) + print(contracts) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/5_DelegationRewards.py b/examples/chain_client/distribution/5_DelegationRewards.py new file mode 100644 index 00000000..da112263 --- /dev/null +++ b/examples/chain_client/distribution/5_DelegationRewards.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + validator_address = "injvaloper156t3yxd4udv0h9gwagfcmwnmm3quy0nph7tyh5" + rewards = await client.fetch_delegation_rewards( + delegator_address=delegator_address, validator_address=validator_address + ) + print(rewards) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/6_DelegationTotalRewards.py b/examples/chain_client/distribution/6_DelegationTotalRewards.py new file mode 100644 index 00000000..c67dc94f --- /dev/null +++ b/examples/chain_client/distribution/6_DelegationTotalRewards.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + rewards = await client.fetch_delegation_total_rewards( + delegator_address=delegator_address, + ) + print(rewards) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/7_DelegatorValidators.py b/examples/chain_client/distribution/7_DelegatorValidators.py new file mode 100644 index 00000000..f03fb8ec --- /dev/null +++ b/examples/chain_client/distribution/7_DelegatorValidators.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + validators = await client.fetch_delegator_validators( + delegator_address=delegator_address, + ) + print(validators) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/8_DelegatorWithdrawAddress.py b/examples/chain_client/distribution/8_DelegatorWithdrawAddress.py new file mode 100644 index 00000000..d3c27091 --- /dev/null +++ b/examples/chain_client/distribution/8_DelegatorWithdrawAddress.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + withdraw_address = await client.fetch_delegator_withdraw_address( + delegator_address=delegator_address, + ) + print(withdraw_address) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/9_CommunityPool.py b/examples/chain_client/distribution/9_CommunityPool.py new file mode 100644 index 00000000..7a803d03 --- /dev/null +++ b/examples/chain_client/distribution/9_CommunityPool.py @@ -0,0 +1,15 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + community_pool = await client.fetch_community_pool() + print(community_pool) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index e8da821b..dea12f12 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -12,6 +12,7 @@ from pyinjective.client.chain.grpc.chain_grpc_auth_api import ChainGrpcAuthApi from pyinjective.client.chain.grpc.chain_grpc_authz_api import ChainGrpcAuthZApi from pyinjective.client.chain.grpc.chain_grpc_bank_api import ChainGrpcBankApi +from pyinjective.client.chain.grpc.chain_grpc_distribution_api import ChainGrpcDistributionApi from pyinjective.client.chain.grpc.chain_grpc_token_factory_api import ChainGrpcTokenFactoryApi from pyinjective.client.chain.grpc.chain_grpc_wasm_api import ChainGrpcWasmApi from pyinjective.client.chain.grpc_stream.chain_grpc_chain_stream import ChainGrpcChainStream @@ -178,6 +179,12 @@ def __init__( metadata_query_provider=self._chain_cookie_metadata_requestor ), ) + self.distribution_api = ChainGrpcDistributionApi( + channel=self.chain_channel, + metadata_provider=lambda: self.network.chain_metadata( + metadata_query_provider=self._chain_cookie_metadata_requestor + ), + ) self.token_factory_api = ChainGrpcTokenFactoryApi( channel=self.chain_channel, metadata_provider=lambda: self.network.chain_metadata( @@ -572,6 +579,66 @@ async def fetch_send_enabled( ) -> Dict[str, Any]: return await self.bank_api.fetch_send_enabled(denoms=denoms, pagination=pagination) + async def fetch_validator_distribution_info(self, validator_address: str) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_distribution_info(validator_address=validator_address) + + async def fetch_validator_outstanding_rewards(self, validator_address: str) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_outstanding_rewards(validator_address=validator_address) + + async def fetch_validator_commission(self, validator_address: str) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_commission(validator_address=validator_address) + + async def fetch_validator_slashes( + self, + validator_address: str, + starting_height: Optional[int] = None, + ending_height: Optional[int] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_slashes( + validator_address=validator_address, + starting_height=starting_height, + ending_height=ending_height, + pagination=pagination, + ) + + async def fetch_delegation_rewards( + self, + delegator_address: str, + validator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegation_rewards( + delegator_address=delegator_address, + validator_address=validator_address, + ) + + async def fetch_delegation_total_rewards( + self, + delegator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegation_total_rewards( + delegator_address=delegator_address, + ) + + async def fetch_delegator_validators( + self, + delegator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegator_validators( + delegator_address=delegator_address, + ) + + async def fetch_delegator_withdraw_address( + self, + delegator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegator_withdraw_address( + delegator_address=delegator_address, + ) + + async def fetch_community_pool(self) -> Dict[str, Any]: + return await self.distribution_api.fetch_community_pool() + # Injective Exchange client methods # Auction RPC diff --git a/pyinjective/client/chain/grpc/chain_grpc_distribution_api.py b/pyinjective/client/chain/grpc/chain_grpc_distribution_api.py new file mode 100644 index 00000000..e7da0966 --- /dev/null +++ b/pyinjective/client/chain/grpc/chain_grpc_distribution_api.py @@ -0,0 +1,109 @@ +from typing import Any, Callable, Dict, Optional + +from grpc.aio import Channel + +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + query_pb2 as distribution_query_pb, + query_pb2_grpc as distribution_query_grpc, +) +from pyinjective.utils.grpc_api_request_assistant import GrpcApiRequestAssistant + + +class ChainGrpcDistributionApi: + def __init__(self, channel: Channel, metadata_provider: Callable): + self._stub = distribution_query_grpc.QueryStub(channel) + self._assistant = GrpcApiRequestAssistant(metadata_provider=metadata_provider) + + async def fetch_module_params(self) -> Dict[str, Any]: + request = distribution_query_pb.QueryParamsRequest() + response = await self._execute_call(call=self._stub.Params, request=request) + + return response + + async def fetch_validator_distribution_info(self, validator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryValidatorDistributionInfoRequest(validator_address=validator_address) + response = await self._execute_call(call=self._stub.ValidatorDistributionInfo, request=request) + + return response + + async def fetch_validator_outstanding_rewards(self, validator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryValidatorOutstandingRewardsRequest(validator_address=validator_address) + response = await self._execute_call(call=self._stub.ValidatorOutstandingRewards, request=request) + + return response + + async def fetch_validator_commission(self, validator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryValidatorCommissionRequest(validator_address=validator_address) + response = await self._execute_call(call=self._stub.ValidatorCommission, request=request) + + return response + + async def fetch_validator_slashes( + self, + validator_address: str, + starting_height: Optional[int] = None, + ending_height: Optional[int] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + pagination_request = None + if pagination is not None: + pagination_request = pagination.create_pagination_request() + request = distribution_query_pb.QueryValidatorSlashesRequest( + validator_address=validator_address, + starting_height=starting_height, + ending_height=ending_height, + pagination=pagination_request, + ) + response = await self._execute_call(call=self._stub.ValidatorSlashes, request=request) + + return response + + async def fetch_delegation_rewards( + self, + delegator_address: str, + validator_address: str, + ) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegationRewardsRequest( + delegator_address=delegator_address, + validator_address=validator_address, + ) + response = await self._execute_call(call=self._stub.DelegationRewards, request=request) + + return response + + async def fetch_delegation_total_rewards( + self, + delegator_address: str, + ) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegationTotalRewardsRequest( + delegator_address=delegator_address, + ) + response = await self._execute_call(call=self._stub.DelegationTotalRewards, request=request) + + return response + + async def fetch_delegator_validators(self, delegator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegatorValidatorsRequest( + delegator_address=delegator_address, + ) + response = await self._execute_call(call=self._stub.DelegatorValidators, request=request) + + return response + + async def fetch_delegator_withdraw_address(self, delegator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegatorWithdrawAddressRequest( + delegator_address=delegator_address, + ) + response = await self._execute_call(call=self._stub.DelegatorWithdrawAddress, request=request) + + return response + + async def fetch_community_pool(self) -> Dict[str, Any]: + request = distribution_query_pb.QueryCommunityPoolRequest() + response = await self._execute_call(call=self._stub.CommunityPool, request=request) + + return response + + async def _execute_call(self, call: Callable, request) -> Dict[str, Any]: + return await self._assistant.execute_call(call=call, request=request) diff --git a/tests/client/chain/grpc/configurable_autz_query_servicer.py b/tests/client/chain/grpc/configurable_authz_query_servicer.py similarity index 100% rename from tests/client/chain/grpc/configurable_autz_query_servicer.py rename to tests/client/chain/grpc/configurable_authz_query_servicer.py diff --git a/tests/client/chain/grpc/configurable_distribution_query_servicer.py b/tests/client/chain/grpc/configurable_distribution_query_servicer.py new file mode 100644 index 00000000..d2e1d7da --- /dev/null +++ b/tests/client/chain/grpc/configurable_distribution_query_servicer.py @@ -0,0 +1,69 @@ +from collections import deque + +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + query_pb2 as distribution_query_pb, + query_pb2_grpc as distribution_query_grpc, +) + + +class ConfigurableDistributionQueryServicer(distribution_query_grpc.QueryServicer): + def __init__(self): + super().__init__() + self.distribution_params = deque() + self.validator_distribution_info_responses = deque() + self.validator_outstanding_rewards_responses = deque() + self.validator_commission_responses = deque() + self.validator_slashes_responses = deque() + self.delegation_rewards_responses = deque() + self.delegation_total_rewards_responses = deque() + self.delegator_validators_responses = deque() + self.delegator_withdraw_address_responses = deque() + self.community_pool_responses = deque() + + async def Params(self, request: distribution_query_pb.QueryParamsRequest, context=None, metadata=None): + return self.distribution_params.pop() + + async def ValidatorDistributionInfo( + self, request: distribution_query_pb.QueryValidatorDistributionInfoRequest, context=None, metadata=None + ): + return self.validator_distribution_info_responses.pop() + + async def ValidatorOutstandingRewards( + self, request: distribution_query_pb.QueryValidatorOutstandingRewardsRequest, context=None, metadata=None + ): + return self.validator_outstanding_rewards_responses.pop() + + async def ValidatorCommission( + self, request: distribution_query_pb.QueryValidatorCommissionRequest, context=None, metadata=None + ): + return self.validator_commission_responses.pop() + + async def ValidatorSlashes( + self, request: distribution_query_pb.QueryValidatorSlashesRequest, context=None, metadata=None + ): + return self.validator_slashes_responses.pop() + + async def DelegationRewards( + self, request: distribution_query_pb.QueryDelegationRewardsRequest, context=None, metadata=None + ): + return self.delegation_rewards_responses.pop() + + async def DelegationTotalRewards( + self, request: distribution_query_pb.QueryDelegationTotalRewardsRequest, context=None, metadata=None + ): + return self.delegation_total_rewards_responses.pop() + + async def DelegatorValidators( + self, request: distribution_query_pb.QueryDelegatorValidatorsRequest, context=None, metadata=None + ): + return self.delegator_validators_responses.pop() + + async def DelegatorWithdrawAddress( + self, request: distribution_query_pb.QueryDelegatorWithdrawAddressRequest, context=None, metadata=None + ): + return self.delegator_withdraw_address_responses.pop() + + async def CommunityPool( + self, request: distribution_query_pb.QueryCommunityPoolRequest, context=None, metadata=None + ): + return self.community_pool_responses.pop() diff --git a/tests/client/chain/grpc/test_chain_grpc_distribution_api.py b/tests/client/chain/grpc/test_chain_grpc_distribution_api.py new file mode 100644 index 00000000..9f8ee9a6 --- /dev/null +++ b/tests/client/chain/grpc/test_chain_grpc_distribution_api.py @@ -0,0 +1,338 @@ +import base64 + +import grpc +import pytest + +from pyinjective.client.chain.grpc.chain_grpc_distribution_api import ChainGrpcDistributionApi +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network +from pyinjective.proto.cosmos.base.query.v1beta1 import pagination_pb2 as pagination_pb +from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as coin_pb +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + distribution_pb2 as distribution_pb, + query_pb2 as distribution_query_pb, +) +from tests.client.chain.grpc.configurable_distribution_query_servicer import ConfigurableDistributionQueryServicer + + +@pytest.fixture +def distribution_servicer(): + return ConfigurableDistributionQueryServicer() + + +class TestChainGrpcAuthApi: + @pytest.mark.asyncio + async def test_fetch_module_params( + self, + distribution_servicer, + ): + params = distribution_pb.Params( + community_tax="0.050000000000000000", + base_proposer_reward="0.060000000000000000", + bonus_proposer_reward="0.070000000000000000", + withdraw_addr_enabled=True, + ) + + distribution_servicer.distribution_params.append(distribution_query_pb.QueryParamsResponse(params=params)) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + module_params = await api.fetch_module_params() + expected_params = { + "params": { + "communityTax": params.community_tax, + "baseProposerReward": params.base_proposer_reward, + "bonusProposerReward": params.bonus_proposer_reward, + "withdrawAddrEnabled": params.withdraw_addr_enabled, + } + } + + assert expected_params == module_params + + @pytest.mark.asyncio + async def test_fetch_validator_distribution_info( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + commission = coin_pb.DecCoin(denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", amount="54497408") + + distribution_servicer.validator_distribution_info_responses.append( + distribution_query_pb.QueryValidatorDistributionInfoResponse( + operator_address=operator, self_bond_rewards=[reward], commission=[commission] + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + validator_info = await api.fetch_validator_distribution_info(validator_address=operator) + expected_info = { + "operatorAddress": operator, + "selfBondRewards": [{"denom": reward.denom, "amount": reward.amount}], + "commission": [{"denom": commission.denom, "amount": commission.amount}], + } + + assert expected_info == validator_info + + @pytest.mark.asyncio + async def test_fetch_validator_outstanding_rewards( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + rewards = distribution_pb.ValidatorOutstandingRewards(rewards=[reward]) + + distribution_servicer.validator_outstanding_rewards_responses.append( + distribution_query_pb.QueryValidatorOutstandingRewardsResponse( + rewards=rewards, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + validator_rewards = await api.fetch_validator_outstanding_rewards(validator_address=operator) + expected_rewards = {"rewards": {"rewards": [{"denom": reward.denom, "amount": reward.amount}]}} + + assert expected_rewards == validator_rewards + + @pytest.mark.asyncio + async def test_fetch_validator_commission( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + first_commission = coin_pb.DecCoin(denom="inj", amount="1000000000") + commission = distribution_pb.ValidatorAccumulatedCommission(commission=[first_commission]) + + distribution_servicer.validator_commission_responses.append( + distribution_query_pb.QueryValidatorCommissionResponse( + commission=commission, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + commission = await api.fetch_validator_commission(validator_address=operator) + expected_commission = { + "commission": {"commission": [{"denom": first_commission.denom, "amount": first_commission.amount}]} + } + + assert expected_commission == commission + + @pytest.mark.asyncio + async def test_fetch_validator_slashes( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + slash = distribution_pb.ValidatorSlashEvent( + validator_period=1, + fraction="4", + ) + pagination = pagination_pb.PageResponse(total=2) + + distribution_servicer.validator_slashes_responses.append( + distribution_query_pb.QueryValidatorSlashesResponse( + slashes=[slash], + pagination=pagination, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + slashes = await api.fetch_validator_slashes( + validator_address=operator, + starting_height=20, + ending_height=100, + pagination=PaginationOption( + skip=0, + limit=100, + ), + ) + expected_slashes = { + "slashes": [ + { + "validatorPeriod": str(slash.validator_period), + "fraction": slash.fraction, + } + ], + "pagination": {"nextKey": base64.b64encode(pagination.next_key).decode(), "total": str(pagination.total)}, + } + + assert slashes == expected_slashes + + @pytest.mark.asyncio + async def test_fetch_delegation_rewards( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + validator = "injvaloper16gdnrnl224ylje5z9vd0vn0msym7p58f00qauj" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + + distribution_servicer.delegation_rewards_responses.append( + distribution_query_pb.QueryDelegationRewardsResponse( + rewards=[reward], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + rewards = await api.fetch_delegation_rewards( + delegator_address=delegator, + validator_address=validator, + ) + expected_rewards = {"rewards": [{"denom": reward.denom, "amount": reward.amount}]} + + assert rewards == expected_rewards + + @pytest.mark.asyncio + async def test_fetch_delegation_total_rewards( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + validator = "injvaloper16gdnrnl224ylje5z9vd0vn0msym7p58f00qauj" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + delegation_delegator_reward = distribution_pb.DelegationDelegatorReward( + validator_address=validator, + reward=[reward], + ) + total = coin_pb.DecCoin(denom="inj", amount="2000000000") + + distribution_servicer.delegation_total_rewards_responses.append( + distribution_query_pb.QueryDelegationTotalRewardsResponse( + rewards=[delegation_delegator_reward], + total=[total], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + rewards = await api.fetch_delegation_total_rewards( + delegator_address=delegator, + ) + expected_rewards = { + "rewards": [ + { + "validatorAddress": validator, + "reward": [{"denom": reward.denom, "amount": reward.amount}], + } + ], + "total": [{"denom": total.denom, "amount": total.amount}], + } + + assert rewards == expected_rewards + + @pytest.mark.asyncio + async def test_fetch_delegator_validators( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + validator = "injvaloper16gdnrnl224ylje5z9vd0vn0msym7p58f00qauj" + + distribution_servicer.delegator_validators_responses.append( + distribution_query_pb.QueryDelegatorValidatorsResponse( + validators=[validator], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + validators = await api.fetch_delegator_validators( + delegator_address=delegator, + ) + expected_validators = { + "validators": [validator], + } + + assert validators == expected_validators + + @pytest.mark.asyncio + async def test_fetch_delegator_withdraw_address( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + + distribution_servicer.delegator_withdraw_address_responses.append( + distribution_query_pb.QueryDelegatorWithdrawAddressResponse( + withdraw_address=delegator, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + withdraw_address = await api.fetch_delegator_withdraw_address( + delegator_address=delegator, + ) + expected_withdraw_address = { + "withdrawAddress": delegator, + } + + assert withdraw_address == expected_withdraw_address + + @pytest.mark.asyncio + async def test_fetch_community_pool( + self, + distribution_servicer, + ): + coin = coin_pb.DecCoin(denom="inj", amount="1000000000") + distribution_servicer.community_pool_responses.append( + distribution_query_pb.QueryCommunityPoolResponse( + pool=[coin], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + community_pool = await api.fetch_community_pool() + expected_community_pool = {"pool": [{"denom": coin.denom, "amount": coin.amount}]} + + assert community_pool == expected_community_pool + + async def _dummy_metadata_provider(self): + return None From 51a73f40028ff32ba49848b254cbde1c661f81c9 Mon Sep 17 00:00:00 2001 From: abel Date: Fri, 9 Feb 2024 00:16:59 -0300 Subject: [PATCH 07/44] (fix) Fix error due to incomplete rename --- tests/client/chain/grpc/test_chain_grpc_authz_api.py | 2 +- tests/test_async_client_deprecation_warnings.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/client/chain/grpc/test_chain_grpc_authz_api.py b/tests/client/chain/grpc/test_chain_grpc_authz_api.py index e097ff66..9d1d5586 100644 --- a/tests/client/chain/grpc/test_chain_grpc_authz_api.py +++ b/tests/client/chain/grpc/test_chain_grpc_authz_api.py @@ -7,7 +7,7 @@ from pyinjective.core.network import Network from pyinjective.proto.cosmos.authz.v1beta1 import authz_pb2, query_pb2 as authz_query from pyinjective.proto.cosmos.base.query.v1beta1 import pagination_pb2 as pagination_pb -from tests.client.chain.grpc.configurable_autz_query_servicer import ConfigurableAuthZQueryServicer +from tests.client.chain.grpc.configurable_authz_query_servicer import ConfigurableAuthZQueryServicer @pytest.fixture diff --git a/tests/test_async_client_deprecation_warnings.py b/tests/test_async_client_deprecation_warnings.py index dae2d807..1df77fe8 100644 --- a/tests/test_async_client_deprecation_warnings.py +++ b/tests/test_async_client_deprecation_warnings.py @@ -21,7 +21,7 @@ from pyinjective.proto.injective.stream.v1beta1 import query_pb2 as chain_stream_pb from pyinjective.proto.injective.types.v1beta1 import account_pb2 as account_pb from tests.client.chain.grpc.configurable_auth_query_servicer import ConfigurableAuthQueryServicer -from tests.client.chain.grpc.configurable_autz_query_servicer import ConfigurableAuthZQueryServicer +from tests.client.chain.grpc.configurable_authz_query_servicer import ConfigurableAuthZQueryServicer from tests.client.chain.grpc.configurable_bank_query_servicer import ConfigurableBankQueryServicer from tests.client.chain.stream_grpc.configurable_chain_stream_query_servicer import ConfigurableChainStreamQueryServicer from tests.client.indexer.configurable_account_query_servicer import ConfigurableAccountQueryServicer From 03b81d612333d6f3adcacc08e2838549cfbd6fed Mon Sep 17 00:00:00 2001 From: abel Date: Mon, 12 Feb 2024 15:44:17 -0300 Subject: [PATCH 08/44] (feat) Added support in Composer to create all missing messages from the `distribution` module. Marked as deprecated old functions not following Python naming standards and created the replacements for them (with the correct name following standards) --- examples/chain_client/0_LocalOrderHash.py | 6 +- .../13_MsgIncreasePositionMargin.py | 2 +- examples/chain_client/15_MsgWithdraw.py | 2 +- .../chain_client/16_MsgSubaccountTransfer.py | 2 +- .../chain_client/17_MsgBatchUpdateOrders.py | 2 +- examples/chain_client/18_MsgBid.py | 2 +- examples/chain_client/19_MsgGrant.py | 2 +- examples/chain_client/1_MsgSend.py | 2 +- examples/chain_client/20_MsgExec.py | 2 +- examples/chain_client/21_MsgRevoke.py | 2 +- examples/chain_client/22_MsgSendToEth.py | 2 +- .../chain_client/23_MsgRelayPriceFeedPrice.py | 2 +- examples/chain_client/24_MsgRewardsOptOut.py | 2 +- examples/chain_client/25_MsgDelegate.py | 2 +- .../26_MsgWithdrawDelegatorReward.py | 81 ----------- examples/chain_client/2_MsgDeposit.py | 2 +- examples/chain_client/30_ExternalTransfer.py | 2 +- .../31_MsgCreateBinaryOptionsLimitOrder.py | 2 +- .../32_MsgCreateBinaryOptionsMarketOrder.py | 2 +- .../33_MsgCancelBinaryOptionsOrder.py | 2 +- .../34_MsgAdminUpdateBinaryOptionsMarket.py | 2 +- .../35_MsgInstantBinaryOptionsMarketLaunch.py | 2 +- .../chain_client/36_MsgRelayProviderPrices.py | 2 +- .../chain_client/3_MsgCreateSpotLimitOrder.py | 2 +- .../chain_client/40_MsgExecuteContract.py | 8 +- .../chain_client/41_MsgCreateInsuranceFund.py | 2 +- examples/chain_client/42_MsgUnderwrite.py | 2 +- .../chain_client/43_MsgRequestRedemption.py | 2 +- ...8_WithdrawValidatorCommissionAndRewards.py | 86 ------------ .../4_MsgCreateSpotMarketOrder.py | 2 +- examples/chain_client/5_MsgCancelSpotOrder.py | 2 +- .../6_MsgCreateDerivativeLimitOrder.py | 2 +- examples/chain_client/72_MsgMint.py | 2 +- examples/chain_client/73_MsgBurn.py | 2 +- .../76_MsgExecuteContractCompat.py | 2 +- .../chain_client/77_MsgLiquidatePosition.py | 2 +- .../7_MsgCreateDerivativeMarketOrder.py | 2 +- .../8_MsgCancelDerivativeOrder.py | 2 +- .../distribution/10_SetWithdrawAddress.py | 46 ++++++ .../11_WithdrawDelegatorReward.py | 47 +++++++ .../12_WithdrawValidatorCommission.py | 45 ++++++ .../distribution/13_FundCommunityPool.py | 47 +++++++ pyinjective/composer.py | 132 +++++++++++++----- pyinjective/core/broadcaster.py | 4 +- tests/test_composer.py | 4 +- 45 files changed, 325 insertions(+), 249 deletions(-) delete mode 100644 examples/chain_client/26_MsgWithdrawDelegatorReward.py delete mode 100644 examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py create mode 100644 examples/chain_client/distribution/10_SetWithdrawAddress.py create mode 100644 examples/chain_client/distribution/11_WithdrawDelegatorReward.py create mode 100644 examples/chain_client/distribution/12_WithdrawValidatorCommission.py create mode 100644 examples/chain_client/distribution/13_FundCommunityPool.py diff --git a/examples/chain_client/0_LocalOrderHash.py b/examples/chain_client/0_LocalOrderHash.py index a25398c6..770ad5bf 100644 --- a/examples/chain_client/0_LocalOrderHash.py +++ b/examples/chain_client/0_LocalOrderHash.py @@ -113,7 +113,7 @@ async def main() -> None: gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) @@ -150,7 +150,7 @@ async def main() -> None: gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) @@ -240,7 +240,7 @@ async def main() -> None: gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/13_MsgIncreasePositionMargin.py b/examples/chain_client/13_MsgIncreasePositionMargin.py index f54910f8..775a41e5 100644 --- a/examples/chain_client/13_MsgIncreasePositionMargin.py +++ b/examples/chain_client/13_MsgIncreasePositionMargin.py @@ -66,7 +66,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/15_MsgWithdraw.py b/examples/chain_client/15_MsgWithdraw.py index a8c267d8..b198c0aa 100644 --- a/examples/chain_client/15_MsgWithdraw.py +++ b/examples/chain_client/15_MsgWithdraw.py @@ -57,7 +57,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/16_MsgSubaccountTransfer.py b/examples/chain_client/16_MsgSubaccountTransfer.py index d87eb0ed..b68717b2 100644 --- a/examples/chain_client/16_MsgSubaccountTransfer.py +++ b/examples/chain_client/16_MsgSubaccountTransfer.py @@ -64,7 +64,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/17_MsgBatchUpdateOrders.py b/examples/chain_client/17_MsgBatchUpdateOrders.py index 557ffe46..9efdc0a0 100644 --- a/examples/chain_client/17_MsgBatchUpdateOrders.py +++ b/examples/chain_client/17_MsgBatchUpdateOrders.py @@ -153,7 +153,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/18_MsgBid.py b/examples/chain_client/18_MsgBid.py index 8e5f8d5e..1efaa3e3 100644 --- a/examples/chain_client/18_MsgBid.py +++ b/examples/chain_client/18_MsgBid.py @@ -56,7 +56,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/19_MsgGrant.py b/examples/chain_client/19_MsgGrant.py index 32a82fe7..111a050c 100644 --- a/examples/chain_client/19_MsgGrant.py +++ b/examples/chain_client/19_MsgGrant.py @@ -76,7 +76,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/1_MsgSend.py b/examples/chain_client/1_MsgSend.py index 6389c8be..1d926898 100644 --- a/examples/chain_client/1_MsgSend.py +++ b/examples/chain_client/1_MsgSend.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/20_MsgExec.py b/examples/chain_client/20_MsgExec.py index d5ff2dc5..1203ff90 100644 --- a/examples/chain_client/20_MsgExec.py +++ b/examples/chain_client/20_MsgExec.py @@ -83,7 +83,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/21_MsgRevoke.py b/examples/chain_client/21_MsgRevoke.py index 82663004..91bb192d 100644 --- a/examples/chain_client/21_MsgRevoke.py +++ b/examples/chain_client/21_MsgRevoke.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/22_MsgSendToEth.py b/examples/chain_client/22_MsgSendToEth.py index 59bdc877..06e2d78c 100644 --- a/examples/chain_client/22_MsgSendToEth.py +++ b/examples/chain_client/22_MsgSendToEth.py @@ -70,7 +70,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/23_MsgRelayPriceFeedPrice.py b/examples/chain_client/23_MsgRelayPriceFeedPrice.py index cc7055c9..b59b34a3 100644 --- a/examples/chain_client/23_MsgRelayPriceFeedPrice.py +++ b/examples/chain_client/23_MsgRelayPriceFeedPrice.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/24_MsgRewardsOptOut.py b/examples/chain_client/24_MsgRewardsOptOut.py index 5fa2f429..8beaa1f4 100644 --- a/examples/chain_client/24_MsgRewardsOptOut.py +++ b/examples/chain_client/24_MsgRewardsOptOut.py @@ -56,7 +56,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/25_MsgDelegate.py b/examples/chain_client/25_MsgDelegate.py index ada14ce0..e32f6691 100644 --- a/examples/chain_client/25_MsgDelegate.py +++ b/examples/chain_client/25_MsgDelegate.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/26_MsgWithdrawDelegatorReward.py b/examples/chain_client/26_MsgWithdrawDelegatorReward.py deleted file mode 100644 index f9370c23..00000000 --- a/examples/chain_client/26_MsgWithdrawDelegatorReward.py +++ /dev/null @@ -1,81 +0,0 @@ -import asyncio -import os - -import dotenv -from grpc import RpcError - -from pyinjective.async_client import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE -from pyinjective.core.network import Network -from pyinjective.transaction import Transaction -from pyinjective.wallet import PrivateKey - - -async def main() -> None: - dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") - - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - composer = await client.composer() - await client.sync_timeout_height() - - # load account - priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - # prepare tx msg - validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" - - msg = composer.MsgWithdrawDelegatorReward( - delegator_address=address.to_acc_bech32(), validator_address=validator_address - ) - - # build sim tx - tx = ( - Transaction() - .with_messages(msg) - .with_sequence(client.get_sequence()) - .with_account_num(client.get_number()) - .with_chain_id(network.chain_id) - ) - sim_sign_doc = tx.get_sign_doc(pub_key) - sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) - sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key) - - # simulate tx - try: - sim_res = await client.simulate(sim_tx_raw_bytes) - except RpcError as ex: - print(ex) - return - - # build tx - gas_price = GAS_PRICE - gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation - gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") - fee = [ - composer.Coin( - amount=gas_price * gas_limit, - denom=network.fee_denom, - ) - ] - tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height) - sign_doc = tx.get_sign_doc(pub_key) - sig = priv_key.sign(sign_doc.SerializeToString()) - tx_raw_bytes = tx.get_tx_data(sig, pub_key) - - # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode - res = await client.broadcast_tx_sync_mode(tx_raw_bytes) - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/2_MsgDeposit.py b/examples/chain_client/2_MsgDeposit.py index 80587c55..80b9f652 100644 --- a/examples/chain_client/2_MsgDeposit.py +++ b/examples/chain_client/2_MsgDeposit.py @@ -57,7 +57,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/30_ExternalTransfer.py b/examples/chain_client/30_ExternalTransfer.py index 7ab6e0f2..3200be34 100644 --- a/examples/chain_client/30_ExternalTransfer.py +++ b/examples/chain_client/30_ExternalTransfer.py @@ -64,7 +64,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py index 57f5537b..2a58e173 100644 --- a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py +++ b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py @@ -81,7 +81,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py index 473e8e53..2d07658f 100644 --- a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py +++ b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py @@ -75,7 +75,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py index 15159f00..82107f3c 100644 --- a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py +++ b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py @@ -66,7 +66,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py index 55c308be..0f39dcdb 100644 --- a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py +++ b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py @@ -74,7 +74,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py index 7e865320..7b8a6567 100644 --- a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py +++ b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py @@ -76,7 +76,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/36_MsgRelayProviderPrices.py b/examples/chain_client/36_MsgRelayProviderPrices.py index 4ee5fc3f..1e3b9c8f 100644 --- a/examples/chain_client/36_MsgRelayProviderPrices.py +++ b/examples/chain_client/36_MsgRelayProviderPrices.py @@ -66,7 +66,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/3_MsgCreateSpotLimitOrder.py index dd06672a..d3ca5f16 100644 --- a/examples/chain_client/3_MsgCreateSpotLimitOrder.py +++ b/examples/chain_client/3_MsgCreateSpotLimitOrder.py @@ -77,7 +77,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/40_MsgExecuteContract.py b/examples/chain_client/40_MsgExecuteContract.py index f2d1b719..d18c6398 100644 --- a/examples/chain_client/40_MsgExecuteContract.py +++ b/examples/chain_client/40_MsgExecuteContract.py @@ -33,12 +33,12 @@ async def main() -> None: # prepare tx msg # NOTE: COIN MUST BE SORTED IN ALPHABETICAL ORDER BY DENOMS funds = [ - composer.Coin( + composer.coin( amount=69, denom="factory/inj1hdvy6tl89llqy3ze8lv6mz5qh66sx9enn0jxg6/inj12ngevx045zpvacus9s6anr258gkwpmthnz80e9", ), - composer.Coin(amount=420, denom="peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7"), - composer.Coin(amount=1, denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"), + composer.coin(amount=420, denom="peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7"), + composer.coin(amount=1, denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"), ] msg = composer.MsgExecuteContract( sender=address.to_acc_bech32(), @@ -71,7 +71,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/41_MsgCreateInsuranceFund.py b/examples/chain_client/41_MsgCreateInsuranceFund.py index 74f94bfa..99c10fc0 100644 --- a/examples/chain_client/41_MsgCreateInsuranceFund.py +++ b/examples/chain_client/41_MsgCreateInsuranceFund.py @@ -65,7 +65,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/42_MsgUnderwrite.py b/examples/chain_client/42_MsgUnderwrite.py index 20c65a64..16b75e70 100644 --- a/examples/chain_client/42_MsgUnderwrite.py +++ b/examples/chain_client/42_MsgUnderwrite.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/43_MsgRequestRedemption.py b/examples/chain_client/43_MsgRequestRedemption.py index 4413044b..ecc2793c 100644 --- a/examples/chain_client/43_MsgRequestRedemption.py +++ b/examples/chain_client/43_MsgRequestRedemption.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py b/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py deleted file mode 100644 index 2f67f6c4..00000000 --- a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py +++ /dev/null @@ -1,86 +0,0 @@ -import asyncio -import os - -import dotenv -from grpc import RpcError - -from pyinjective.async_client import AsyncClient -from pyinjective.composer import Composer as ProtoMsgComposer -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE -from pyinjective.core.network import Network -from pyinjective.transaction import Transaction -from pyinjective.wallet import PrivateKey - - -async def main() -> None: - dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") - - """For a validator to withdraw his rewards & commissions simultaneously""" - # select network: local, testnet, mainnet - network = Network.testnet() - composer = ProtoMsgComposer(network=network.string()) - - # initialize grpc client - client = AsyncClient(network, insecure=False) - await client.sync_timeout_height() - - # load account - # private key is that from the validator's wallet - priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - # prepare tx msg - validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" - - msg0 = composer.MsgWithdrawDelegatorReward( - delegator_address=address.to_acc_bech32(), validator_address=validator_address - ) - - msg1 = composer.MsgWithdrawValidatorCommission(validator_address=validator_address) - - # build sim tx - tx = ( - Transaction() - .with_messages(msg0, msg1) - .with_sequence(client.get_sequence()) - .with_account_num(client.get_number()) - .with_chain_id(network.chain_id) - ) - sim_sign_doc = tx.get_sign_doc(pub_key) - sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) - sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key) - - # simulate tx - try: - sim_res = await client.simulate(sim_tx_raw_bytes) - except RpcError as ex: - print(ex) - return - - # build tx - gas_price = GAS_PRICE - gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation - gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") - fee = [ - composer.Coin( - amount=gas_price * gas_limit, - denom=network.fee_denom, - ) - ] - tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height) - sign_doc = tx.get_sign_doc(pub_key) - sig = priv_key.sign(sign_doc.SerializeToString()) - tx_raw_bytes = tx.get_tx_data(sig, pub_key) - - # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode - res = await client.broadcast_tx_sync_mode(tx_raw_bytes) - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/4_MsgCreateSpotMarketOrder.py index 06a42a96..5229632f 100644 --- a/examples/chain_client/4_MsgCreateSpotMarketOrder.py +++ b/examples/chain_client/4_MsgCreateSpotMarketOrder.py @@ -75,7 +75,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/5_MsgCancelSpotOrder.py b/examples/chain_client/5_MsgCancelSpotOrder.py index 63167309..970b2190 100644 --- a/examples/chain_client/5_MsgCancelSpotOrder.py +++ b/examples/chain_client/5_MsgCancelSpotOrder.py @@ -63,7 +63,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py index e46f1acb..41a19307 100644 --- a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py @@ -77,7 +77,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/72_MsgMint.py b/examples/chain_client/72_MsgMint.py index d38449be..b6617431 100644 --- a/examples/chain_client/72_MsgMint.py +++ b/examples/chain_client/72_MsgMint.py @@ -26,7 +26,7 @@ async def main() -> None: pub_key = priv_key.to_public_key() address = pub_key.to_address() - amount = composer.Coin(amount=1_000_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") + amount = composer.coin(amount=1_000_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") message = composer.msg_mint( sender=address.to_acc_bech32(), diff --git a/examples/chain_client/73_MsgBurn.py b/examples/chain_client/73_MsgBurn.py index 441f4ee8..c4aa013a 100644 --- a/examples/chain_client/73_MsgBurn.py +++ b/examples/chain_client/73_MsgBurn.py @@ -26,7 +26,7 @@ async def main() -> None: pub_key = priv_key.to_public_key() address = pub_key.to_address() - amount = composer.Coin(amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") + amount = composer.coin(amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") message = composer.msg_burn( sender=address.to_acc_bech32(), diff --git a/examples/chain_client/76_MsgExecuteContractCompat.py b/examples/chain_client/76_MsgExecuteContractCompat.py index 892c125f..a195c7c4 100644 --- a/examples/chain_client/76_MsgExecuteContractCompat.py +++ b/examples/chain_client/76_MsgExecuteContractCompat.py @@ -68,7 +68,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/77_MsgLiquidatePosition.py b/examples/chain_client/77_MsgLiquidatePosition.py index 6dcbacfb..d80ba385 100644 --- a/examples/chain_client/77_MsgLiquidatePosition.py +++ b/examples/chain_client/77_MsgLiquidatePosition.py @@ -83,7 +83,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py index e7e06c62..37b305ed 100644 --- a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py +++ b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py @@ -76,7 +76,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/8_MsgCancelDerivativeOrder.py b/examples/chain_client/8_MsgCancelDerivativeOrder.py index 6a59167a..43180b1f 100644 --- a/examples/chain_client/8_MsgCancelDerivativeOrder.py +++ b/examples/chain_client/8_MsgCancelDerivativeOrder.py @@ -63,7 +63,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/distribution/10_SetWithdrawAddress.py b/examples/chain_client/distribution/10_SetWithdrawAddress.py new file mode 100644 index 00000000..b317a998 --- /dev/null +++ b/examples/chain_client/distribution/10_SetWithdrawAddress.py @@ -0,0 +1,46 @@ +import asyncio +import os + +import dotenv + +from pyinjective import AsyncClient, PrivateKey +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + withdraw_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + + message = composer.msg_set_withdraw_address( + delegator_address=address.to_acc_bech32(), + withdraw_address=withdraw_address, + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/11_WithdrawDelegatorReward.py b/examples/chain_client/distribution/11_WithdrawDelegatorReward.py new file mode 100644 index 00000000..02facdc7 --- /dev/null +++ b/examples/chain_client/distribution/11_WithdrawDelegatorReward.py @@ -0,0 +1,47 @@ +import asyncio +import os + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" + + message = composer.msg_withdraw_delegator_reward( + delegator_address=address.to_acc_bech32(), validator_address=validator_address + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/12_WithdrawValidatorCommission.py b/examples/chain_client/distribution/12_WithdrawValidatorCommission.py new file mode 100644 index 00000000..cd351d1f --- /dev/null +++ b/examples/chain_client/distribution/12_WithdrawValidatorCommission.py @@ -0,0 +1,45 @@ +import asyncio +import os + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" + + message = composer.msg_withdraw_validator_commission(validator_address=validator_address) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/13_FundCommunityPool.py b/examples/chain_client/distribution/13_FundCommunityPool.py new file mode 100644 index 00000000..c60475c8 --- /dev/null +++ b/examples/chain_client/distribution/13_FundCommunityPool.py @@ -0,0 +1,47 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective import AsyncClient, PrivateKey +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + amount = composer.create_coin_amount(amount=Decimal("0.1"), token_name="INJ") + + message = composer.msg_fund_community_pool( + amounts=[amount], + depositor=address.to_acc_bech32(), + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/pyinjective/composer.py b/pyinjective/composer.py index 720920d1..df353d6b 100644 --- a/pyinjective/composer.py +++ b/pyinjective/composer.py @@ -3,6 +3,7 @@ from decimal import Decimal from time import time from typing import Any, Dict, List, Optional +from warnings import warn from google.protobuf import any_pb2, json_format, timestamp_pb2 @@ -13,7 +14,10 @@ from pyinjective.proto.cosmos.authz.v1beta1 import authz_pb2 as cosmos_authz_pb, tx_pb2 as cosmos_authz_tx_pb from pyinjective.proto.cosmos.bank.v1beta1 import bank_pb2 as bank_pb, tx_pb2 as cosmos_bank_tx_pb from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as cosmos_dot_base_dot_v1beta1_dot_coin__pb2 -from pyinjective.proto.cosmos.distribution.v1beta1 import tx_pb2 as cosmos_distribution_tx_pb +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + distribution_pb2 as cosmos_distribution_pb2, + tx_pb2 as cosmos_distribution_tx_pb, +) from pyinjective.proto.cosmos.gov.v1beta1 import tx_pb2 as cosmos_gov_tx_pb from pyinjective.proto.cosmos.staking.v1beta1 import tx_pb2 as cosmos_staking_tx_pb from pyinjective.proto.cosmwasm.wasm.v1 import tx_pb2 as wasm_tx_pb @@ -129,8 +133,27 @@ def __init__( self.tokens = tokens def Coin(self, amount: int, denom: str): + """ + This method is deprecated and will be removed soon. Please use `coin` instead + """ + warn("This method is deprecated. Use coin instead", DeprecationWarning, stacklevel=2) return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=str(amount), denom=denom) + def coin(self, amount: int, denom: str): + """ + This method create an instance of Coin gRPC type, considering the amount is already expressed in chain format + """ + formatted_amount_string = str(int(amount)) + return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=formatted_amount_string, denom=denom) + + def create_coin_amount(self, amount: Decimal, token_name: str): + """ + This method create an instance of Coin gRPC type, considering the amount is already expressed in chain format + """ + token = self.tokens[token_name] + chain_amount = token.chain_formatted_value(human_readable_value=amount) + return self.coin(amount=int(chain_amount), denom=token.denom) + def get_order_mask(self, **kwargs): order_mask = 0 @@ -331,13 +354,12 @@ def BinaryOptionsOrder( ) def MsgSend(self, from_address: str, to_address: str, amount: float, denom: str): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return cosmos_bank_tx_pb.MsgSend( from_address=from_address, to_address=to_address, - amount=[self.Coin(amount=int(be_amount), denom=token.denom)], + amount=[coin], ) def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): @@ -350,13 +372,12 @@ def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): ) def MsgDeposit(self, sender: str, subaccount_id: str, amount: float, denom: str): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgDeposit( sender=sender, subaccount_id=subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=coin, ) def MsgCreateSpotLimitOrder( @@ -709,24 +730,22 @@ def MsgSubaccountTransfer( amount: int, denom: str, ): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgSubaccountTransfer( sender=sender, source_subaccount_id=source_subaccount_id, destination_subaccount_id=destination_subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=be_amount, ) def MsgWithdraw(self, sender: str, subaccount_id: str, amount: float, denom: str): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgWithdraw( sender=sender, subaccount_id=subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=be_amount, ) def MsgExternalTransfer( @@ -737,14 +756,13 @@ def MsgExternalTransfer( amount: int, denom: str, ): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgExternalTransfer( sender=sender, source_subaccount_id=source_subaccount_id, destination_subaccount_id=destination_subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=coin, ) def MsgBid(self, sender: str, bid_amount: float, round: float): @@ -753,7 +771,7 @@ def MsgBid(self, sender: str, bid_amount: float, round: float): return injective_auction_tx_pb.MsgBid( sender=sender, round=round, - bid_amount=self.Coin(amount=int(be_amount), denom=INJ_DENOM), + bid_amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), ) def MsgGrantGeneric(self, granter: str, grantee: str, msg_type: str, expire_in: int): @@ -851,15 +869,14 @@ def MsgRelayPriceFeedPrice(self, sender: list, base: list, quote: list, price: l return injective_oracle_tx_pb.MsgRelayPriceFeedPrice(sender=sender, base=base, quote=quote, price=price) def MsgSendToEth(self, denom: str, sender: str, eth_dest: str, amount: float, bridge_fee: float): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) - be_bridge_fee = token.chain_formatted_value(human_readable_value=Decimal(str(bridge_fee))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + be_bridge_fee = self.create_coin_amount(amount=Decimal(str(bridge_fee)), token_name=denom) return injective_peggy_tx_pb.MsgSendToEth( sender=sender, eth_dest=eth_dest, - amount=self.Coin(amount=int(be_amount), denom=token.denom), - bridge_fee=self.Coin(amount=int(be_bridge_fee), denom=token.denom), + amount=be_amount, + bridge_fee=be_bridge_fee, ) def MsgDelegate(self, delegator_address: str, validator_address: str, amount: float): @@ -868,7 +885,7 @@ def MsgDelegate(self, delegator_address: str, validator_address: str, amount: fl return cosmos_staking_tx_pb.MsgDelegate( delegator_address=delegator_address, validator_address=validator_address, - amount=self.Coin(amount=int(be_amount), denom=INJ_DENOM), + amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), ) def MsgCreateInsuranceFund( @@ -883,7 +900,7 @@ def MsgCreateInsuranceFund( initial_deposit: int, ): token = self.tokens[quote_denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(initial_deposit))) + deposit = self.create_coin_amount(Decimal(str(initial_deposit)), quote_denom) return injective_insurance_tx_pb.MsgCreateInsuranceFund( sender=sender, @@ -893,7 +910,7 @@ def MsgCreateInsuranceFund( oracle_quote=oracle_quote, oracle_type=oracle_type, expiry=expiry, - initial_deposit=self.Coin(amount=int(be_amount), denom=token.denom), + initial_deposit=deposit, ) def MsgUnderwrite( @@ -903,13 +920,12 @@ def MsgUnderwrite( quote_denom: str, amount: int, ): - token = self.tokens[quote_denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=quote_denom) return injective_insurance_tx_pb.MsgUnderwrite( sender=sender, market_id=market_id, - deposit=self.Coin(amount=int(be_amount), denom=token.denom), + deposit=be_amount, ) def MsgRequestRedemption( @@ -922,17 +938,9 @@ def MsgRequestRedemption( return injective_insurance_tx_pb.MsgRequestRedemption( sender=sender, market_id=market_id, - amount=self.Coin(amount=amount, denom=share_denom), + amount=self.coin(amount=amount, denom=share_denom), ) - def MsgWithdrawDelegatorReward(self, delegator_address: str, validator_address: str): - return cosmos_distribution_tx_pb.MsgWithdrawDelegatorReward( - delegator_address=delegator_address, validator_address=validator_address - ) - - def MsgWithdrawValidatorCommission(self, validator_address: str): - return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) - def MsgVote( self, proposal_id: str, @@ -1101,6 +1109,56 @@ def chain_stream_oracle_price_filter( symbols = symbols or ["*"] return chain_stream_query.OraclePriceFilter(symbol=symbols) + # ------------------------------------------------ + # Distribution module's messages + + def msg_set_withdraw_address(self, delegator_address: str, withdraw_address: str): + return cosmos_distribution_tx_pb.MsgSetWithdrawAddress( + delegator_address=delegator_address, withdraw_address=withdraw_address + ) + + # Deprecated + def MsgWithdrawDelegatorReward(self, delegator_address: str, validator_address: str): + """ + This method is deprecated and will be removed soon. Please use `msg_withdraw_delegator_reward` instead + """ + warn("This method is deprecated. Use msg_withdraw_delegator_reward instead", DeprecationWarning, stacklevel=2) + return cosmos_distribution_tx_pb.MsgWithdrawDelegatorReward( + delegator_address=delegator_address, validator_address=validator_address + ) + + def msg_withdraw_delegator_reward(self, delegator_address: str, validator_address: str): + return cosmos_distribution_tx_pb.MsgWithdrawDelegatorReward( + delegator_address=delegator_address, validator_address=validator_address + ) + + def MsgWithdrawValidatorCommission(self, validator_address: str): + """ + This method is deprecated and will be removed soon. Please use `msg_withdraw_validator_commission` instead + """ + warn( + "This method is deprecated. Use msg_withdraw_validator_commission instead", DeprecationWarning, stacklevel=2 + ) + return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) + + def msg_withdraw_validator_commission(self, validator_address: str): + return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) + + def msg_fund_community_pool(self, amounts: List[cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin], depositor: str): + return cosmos_distribution_tx_pb.MsgFundCommunityPool(amount=amounts, depositor=depositor) + + def msg_update_distribution_params(self, authority: str, community_tax: str, withdraw_address_enabled: bool): + params = cosmos_distribution_pb2.Params( + community_tax=community_tax, + withdraw_addr_enabled=withdraw_address_enabled, + ) + return cosmos_distribution_tx_pb.MsgUpdateParams(authority=authority, params=params) + + def msg_community_pool_spend( + self, authority: str, recipient: str, amount: List[cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin] + ): + return cosmos_distribution_tx_pb.MsgCommunityPoolSpend(authority=authority, recipient=recipient, amount=amount) + # data field format: [request-msg-header][raw-byte-msg-response] # you need to figure out this magic prefix number to trim request-msg-header off the data # this method handles only exchange responses diff --git a/pyinjective/core/broadcaster.py b/pyinjective/core/broadcaster.py index 22df562b..f279baea 100644 --- a/pyinjective/core/broadcaster.py +++ b/pyinjective/core/broadcaster.py @@ -264,7 +264,7 @@ async def configure_gas_fee_for_transaction( gas_limit = math.ceil(Decimal(str(sim_res["gasInfo"]["gasUsed"])) * self._gas_limit_adjustment_multiplier) fee = [ - self._composer.Coin( + self._composer.coin( amount=self._gas_price * gas_limit, denom=self._client.network.fee_denom, ) @@ -292,7 +292,7 @@ async def configure_gas_fee_for_transaction( transaction_gas_limit = messages_gas_limit + self.TRANSACTION_GAS_LIMIT fee = [ - self._composer.Coin( + self._composer.coin( amount=math.ceil(self._gas_price * transaction_gas_limit), denom=self._client.network.fee_denom, ) diff --git a/tests/test_composer.py b/tests/test_composer.py index 4f756c79..a0cca2ab 100644 --- a/tests/test_composer.py +++ b/tests/test_composer.py @@ -282,7 +282,7 @@ def test_msg_create_denom(self, basic_composer: Composer): def test_msg_mint(self, basic_composer: Composer): sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" - amount = basic_composer.Coin( + amount = basic_composer.coin( amount=1_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test", ) @@ -297,7 +297,7 @@ def test_msg_mint(self, basic_composer: Composer): def test_msg_burn(self, basic_composer: Composer): sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" - amount = basic_composer.Coin( + amount = basic_composer.coin( amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test", ) From 68c2a089b66a2230c3713b3f6eab1a318ae9a938 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 16 Jan 2024 11:52:25 -0300 Subject: [PATCH 09/44] (fix) Changed version number for dev branch --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e53facef..6b7d593e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "injective-py" -version = "1.3.0" +version = "1.4.0-pre" description = "Injective Python SDK, with Exchange API Client" authors = ["Injective Labs "] license = "Apache-2.0" From 445d44e6fadc4fd7b583a88c8bf2988ffa09b3c7 Mon Sep 17 00:00:00 2001 From: abel Date: Wed, 17 Jan 2024 10:22:45 -0300 Subject: [PATCH 10/44] (feat) Cleaned up the markets initialization logic --- pyinjective/async_client.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index ec42c2ce..e8da821b 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -9,7 +9,6 @@ import grpc from google.protobuf import json_format -from pyinjective import constant from pyinjective.client.chain.grpc.chain_grpc_auth_api import ChainGrpcAuthApi from pyinjective.client.chain.grpc.chain_grpc_authz_api import ChainGrpcAuthZApi from pyinjective.client.chain.grpc.chain_grpc_bank_api import ChainGrpcBankApi @@ -2659,22 +2658,13 @@ async def _initialize_tokens_and_markets(self): ) for market_info in valid_markets: - ticker = market_info["ticker"] - if "/" in ticker: - base_token_symbol, quote_token_symbol = ticker.split(constant.TICKER_TOKENS_SEPARATOR) - else: - base_token_symbol = market_info["baseTokenMeta"]["symbol"] - quote_token_symbol = market_info["quoteTokenMeta"]["symbol"] - base_token = self._token_representation( - symbol=base_token_symbol, token_meta=market_info["baseTokenMeta"], denom=market_info["baseDenom"], tokens_by_denom=tokens_by_denom, tokens_by_symbol=tokens_by_symbol, ) quote_token = self._token_representation( - symbol=quote_token_symbol, token_meta=market_info["quoteTokenMeta"], denom=market_info["quoteDenom"], tokens_by_denom=tokens_by_denom, @@ -2704,10 +2694,7 @@ async def _initialize_tokens_and_markets(self): ) for market_info in valid_markets: - quote_token_symbol = market_info["quoteTokenMeta"]["symbol"] - quote_token = self._token_representation( - symbol=quote_token_symbol, token_meta=market_info["quoteTokenMeta"], denom=market_info["quoteDenom"], tokens_by_denom=tokens_by_denom, @@ -2769,7 +2756,6 @@ async def _initialize_tokens_and_markets(self): def _token_representation( self, - symbol: str, token_meta: Dict[str, Any], denom: str, tokens_by_denom: Dict[str, Token], @@ -2777,14 +2763,14 @@ def _token_representation( ) -> Token: if denom not in tokens_by_denom: unique_symbol = denom - for symbol_candidate in [symbol, token_meta["symbol"], token_meta["name"]]: + for symbol_candidate in [token_meta["symbol"], token_meta["name"]]: if symbol_candidate not in tokens_by_symbol: unique_symbol = symbol_candidate break token = Token( name=token_meta["name"], - symbol=symbol, + symbol=token_meta["symbol"], denom=denom, address=token_meta["address"], decimals=token_meta["decimals"], From 3590e04c0538fa47817b163bd83ea797c8076de0 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 6 Feb 2024 16:50:12 -0300 Subject: [PATCH 11/44] (feat) Refactored all examples to remove references to private keys. Added the use of `dotenv` to load private keys into environment variables. Removed `asyncio` package dependency --- examples/SendToInjective.py | 7 +- examples/chain_client/0_LocalOrderHash.py | 8 +- .../13_MsgIncreasePositionMargin.py | 7 +- examples/chain_client/15_MsgWithdraw.py | 7 +- .../chain_client/16_MsgSubaccountTransfer.py | 7 +- .../chain_client/17_MsgBatchUpdateOrders.py | 7 +- examples/chain_client/18_MsgBid.py | 7 +- examples/chain_client/19_MsgGrant.py | 12 +- examples/chain_client/1_MsgSend.py | 7 +- examples/chain_client/20_MsgExec.py | 12 +- examples/chain_client/21_MsgRevoke.py | 12 +- examples/chain_client/22_MsgSendToEth.py | 7 +- .../chain_client/23_MsgRelayPriceFeedPrice.py | 7 +- examples/chain_client/24_MsgRewardsOptOut.py | 7 +- examples/chain_client/25_MsgDelegate.py | 7 +- .../26_MsgWithdrawDelegatorReward.py | 7 +- examples/chain_client/27_Grants.py | 9 +- examples/chain_client/2_MsgDeposit.py | 9 +- examples/chain_client/30_ExternalTransfer.py | 7 +- .../31_MsgCreateBinaryOptionsLimitOrder.py | 7 +- .../32_MsgCreateBinaryOptionsMarketOrder.py | 7 +- .../33_MsgCancelBinaryOptionsOrder.py | 7 +- .../34_MsgAdminUpdateBinaryOptionsMarket.py | 7 +- .../35_MsgInstantBinaryOptionsMarketLaunch.py | 7 +- .../chain_client/36_MsgRelayProviderPrices.py | 7 +- .../chain_client/3_MsgCreateSpotLimitOrder.py | 7 +- .../chain_client/40_MsgExecuteContract.py | 7 +- .../chain_client/41_MsgCreateInsuranceFund.py | 7 +- examples/chain_client/42_MsgUnderwrite.py | 7 +- .../chain_client/43_MsgRequestRedemption.py | 7 +- .../chain_client/44_MessageBroadcaster.py | 7 +- ...45_MessageBroadcasterWithGranteeAccount.py | 10 +- .../46_MessageBroadcasterWithoutSimulation.py | 7 +- ...sterWithGranteeAccountWithoutSimulation.py | 9 +- ...8_WithdrawValidatorCommissionAndRewards.py | 7 +- .../4_MsgCreateSpotMarketOrder.py | 7 +- examples/chain_client/5_MsgCancelSpotOrder.py | 7 +- .../6_MsgCreateDerivativeLimitOrder.py | 7 +- examples/chain_client/71_CreateDenom.py | 7 +- examples/chain_client/72_MsgMint.py | 7 +- examples/chain_client/73_MsgBurn.py | 7 +- .../chain_client/74_MsgSetDenomMetadata.py | 7 +- examples/chain_client/75_MsgChangeAdmin.py | 7 +- .../76_MsgExecuteContractCompat.py | 7 +- .../chain_client/77_MsgLiquidatePosition.py | 7 +- .../7_MsgCreateDerivativeMarketOrder.py | 7 +- .../8_MsgCancelDerivativeOrder.py | 7 +- poetry.lock | 54 +++++--- pyinjective/denoms_devnet.ini | 13 ++ pyinjective/denoms_mainnet.ini | 116 +++++++++++++++--- pyinjective/denoms_testnet.ini | 2 +- pyproject.toml | 3 +- 52 files changed, 445 insertions(+), 97 deletions(-) diff --git a/examples/SendToInjective.py b/examples/SendToInjective.py index b03988b4..23469642 100644 --- a/examples/SendToInjective.py +++ b/examples/SendToInjective.py @@ -1,16 +1,21 @@ import asyncio import json +import os + +import dotenv from pyinjective.core.network import Network from pyinjective.sendtocosmos import Peggo async def main() -> None: + dotenv.load_dotenv() + private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: testnet, mainnet network = Network.testnet() peggo_composer = Peggo(network=network.string()) - private_key = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" ethereum_endpoint = "https://eth-goerli.g.alchemy.com/v2/q-7JVv4mTfsNh1y_djKkKn3maRBGILLL" maxFeePerGas_Gwei = 4 diff --git a/examples/chain_client/0_LocalOrderHash.py b/examples/chain_client/0_LocalOrderHash.py index c81c3e2e..a25398c6 100644 --- a/examples/chain_client/0_LocalOrderHash.py +++ b/examples/chain_client/0_LocalOrderHash.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.async_client import AsyncClient from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE from pyinjective.core.network import Network @@ -10,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/13_MsgIncreasePositionMargin.py b/examples/chain_client/13_MsgIncreasePositionMargin.py index 27d42884..f54910f8 100644 --- a/examples/chain_client/13_MsgIncreasePositionMargin.py +++ b/examples/chain_client/13_MsgIncreasePositionMargin.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/15_MsgWithdraw.py b/examples/chain_client/15_MsgWithdraw.py index 9fc1e359..a8c267d8 100644 --- a/examples/chain_client/15_MsgWithdraw.py +++ b/examples/chain_client/15_MsgWithdraw.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/16_MsgSubaccountTransfer.py b/examples/chain_client/16_MsgSubaccountTransfer.py index 5a18b1dd..d87eb0ed 100644 --- a/examples/chain_client/16_MsgSubaccountTransfer.py +++ b/examples/chain_client/16_MsgSubaccountTransfer.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/17_MsgBatchUpdateOrders.py b/examples/chain_client/17_MsgBatchUpdateOrders.py index 25147452..557ffe46 100644 --- a/examples/chain_client/17_MsgBatchUpdateOrders.py +++ b/examples/chain_client/17_MsgBatchUpdateOrders.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/18_MsgBid.py b/examples/chain_client/18_MsgBid.py index 9e51e075..8e5f8d5e 100644 --- a/examples/chain_client/18_MsgBid.py +++ b/examples/chain_client/18_MsgBid.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/19_MsgGrant.py b/examples/chain_client/19_MsgGrant.py index 0d00d489..32a82fe7 100644 --- a/examples/chain_client/19_MsgGrant.py +++ b/examples/chain_client/19_MsgGrant.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) @@ -30,8 +36,8 @@ async def main() -> None: # GENERIC AUTHZ msg = composer.MsgGrantGeneric( - granter="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", - grantee="inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku", + granter=address.to_acc_bech32(), + grantee=grantee_public_address, msg_type="/injective.exchange.v1beta1.MsgCreateSpotLimitOrder", expire_in=31536000, # 1 year ) diff --git a/examples/chain_client/1_MsgSend.py b/examples/chain_client/1_MsgSend.py index 9b9651f7..6389c8be 100644 --- a/examples/chain_client/1_MsgSend.py +++ b/examples/chain_client/1_MsgSend.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/20_MsgExec.py b/examples/chain_client/20_MsgExec.py index a2876d6a..d5ff2dc5 100644 --- a/examples/chain_client/20_MsgExec.py +++ b/examples/chain_client/20_MsgExec.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,10 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") + granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,15 +26,15 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) # prepare tx msg market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - grantee = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku" - granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + grantee = address.to_acc_bech32() + granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) msg0 = composer.MsgCreateSpotLimitOrder( diff --git a/examples/chain_client/21_MsgRevoke.py b/examples/chain_client/21_MsgRevoke.py index 2cafab7f..82663004 100644 --- a/examples/chain_client/21_MsgRevoke.py +++ b/examples/chain_client/21_MsgRevoke.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,15 +25,15 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) # prepare tx msg msg = composer.MsgRevoke( - granter="inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku", - grantee="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + granter=address.to_acc_bech32(), + grantee=grantee_public_address, msg_type="/injective.exchange.v1beta1.MsgCreateSpotLimitOrder", ) diff --git a/examples/chain_client/22_MsgSendToEth.py b/examples/chain_client/22_MsgSendToEth.py index 1cb1e677..59bdc877 100644 --- a/examples/chain_client/22_MsgSendToEth.py +++ b/examples/chain_client/22_MsgSendToEth.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv import requests from grpc import RpcError @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/23_MsgRelayPriceFeedPrice.py b/examples/chain_client/23_MsgRelayPriceFeedPrice.py index 38b389de..cc7055c9 100644 --- a/examples/chain_client/23_MsgRelayPriceFeedPrice.py +++ b/examples/chain_client/23_MsgRelayPriceFeedPrice.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/24_MsgRewardsOptOut.py b/examples/chain_client/24_MsgRewardsOptOut.py index bbc8d348..5fa2f429 100644 --- a/examples/chain_client/24_MsgRewardsOptOut.py +++ b/examples/chain_client/24_MsgRewardsOptOut.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/25_MsgDelegate.py b/examples/chain_client/25_MsgDelegate.py index dc95f035..ada14ce0 100644 --- a/examples/chain_client/25_MsgDelegate.py +++ b/examples/chain_client/25_MsgDelegate.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/26_MsgWithdrawDelegatorReward.py b/examples/chain_client/26_MsgWithdrawDelegatorReward.py index 77210421..f9370c23 100644 --- a/examples/chain_client/26_MsgWithdrawDelegatorReward.py +++ b/examples/chain_client/26_MsgWithdrawDelegatorReward.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/27_Grants.py b/examples/chain_client/27_Grants.py index 331980af..9ab27f22 100644 --- a/examples/chain_client/27_Grants.py +++ b/examples/chain_client/27_Grants.py @@ -1,14 +1,19 @@ import asyncio +import os + +import dotenv from pyinjective.async_client import AsyncClient from pyinjective.core.network import Network async def main() -> None: + dotenv.load_dotenv() + granter = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + grantee = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + network = Network.testnet() client = AsyncClient(network) - granter = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku" - grantee = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" msg_type_url = "/injective.exchange.v1beta1.MsgCreateDerivativeLimitOrder" authorizations = await client.fetch_grants(granter=granter, grantee=grantee, msg_type_url=msg_type_url) print(authorizations) diff --git a/examples/chain_client/2_MsgDeposit.py b/examples/chain_client/2_MsgDeposit.py index 9c137b49..80587c55 100644 --- a/examples/chain_client/2_MsgDeposit.py +++ b/examples/chain_client/2_MsgDeposit.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,8 +12,11 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet - network = Network.testnet(node="sentry") + network = Network.testnet() # initialize grpc client client = AsyncClient(network) @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/30_ExternalTransfer.py b/examples/chain_client/30_ExternalTransfer.py index d657c15a..7ab6e0f2 100644 --- a/examples/chain_client/30_ExternalTransfer.py +++ b/examples/chain_client/30_ExternalTransfer.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py index 137529ea..57f5537b 100644 --- a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py +++ b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -12,6 +14,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -21,7 +26,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py index 67004f17..473e8e53 100644 --- a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py +++ b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py index 2631ab26..15159f00 100644 --- a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py +++ b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py index d9eb1e18..55c308be 100644 --- a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py +++ b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py index e0881db5..7e865320 100644 --- a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py +++ b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/36_MsgRelayProviderPrices.py b/examples/chain_client/36_MsgRelayProviderPrices.py index 0fb26b4f..4ee5fc3f 100644 --- a/examples/chain_client/36_MsgRelayProviderPrices.py +++ b/examples/chain_client/36_MsgRelayProviderPrices.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/3_MsgCreateSpotLimitOrder.py index 8d873354..dd06672a 100644 --- a/examples/chain_client/3_MsgCreateSpotLimitOrder.py +++ b/examples/chain_client/3_MsgCreateSpotLimitOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/40_MsgExecuteContract.py b/examples/chain_client/40_MsgExecuteContract.py index fef42954..f2d1b719 100644 --- a/examples/chain_client/40_MsgExecuteContract.py +++ b/examples/chain_client/40_MsgExecuteContract.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/41_MsgCreateInsuranceFund.py b/examples/chain_client/41_MsgCreateInsuranceFund.py index b402dc26..74f94bfa 100644 --- a/examples/chain_client/41_MsgCreateInsuranceFund.py +++ b/examples/chain_client/41_MsgCreateInsuranceFund.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/42_MsgUnderwrite.py b/examples/chain_client/42_MsgUnderwrite.py index 9a14b3ce..20c65a64 100644 --- a/examples/chain_client/42_MsgUnderwrite.py +++ b/examples/chain_client/42_MsgUnderwrite.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/43_MsgRequestRedemption.py b/examples/chain_client/43_MsgRequestRedemption.py index 6ba0fe31..4413044b 100644 --- a/examples/chain_client/43_MsgRequestRedemption.py +++ b/examples/chain_client/43_MsgRequestRedemption.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/44_MessageBroadcaster.py b/examples/chain_client/44_MessageBroadcaster.py index a9bb1f68..114a8700 100644 --- a/examples/chain_client/44_MessageBroadcaster.py +++ b/examples/chain_client/44_MessageBroadcaster.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network @@ -8,10 +11,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py b/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py index 59c04af2..8c0166e2 100644 --- a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py +++ b/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.async_client import AsyncClient from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -9,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") + granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) @@ -18,7 +25,6 @@ async def main() -> None: await client.sync_timeout_height() # load account - private_key_in_hexa = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() @@ -30,7 +36,7 @@ async def main() -> None: # prepare tx msg market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) diff --git a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py b/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py index 908a4579..e6e87c5a 100644 --- a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py +++ b/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network @@ -8,10 +11,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( network=network, diff --git a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py b/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py index ebae28ab..b95114b7 100644 --- a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py +++ b/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.async_client import AsyncClient from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -9,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") + granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) @@ -18,7 +25,6 @@ async def main() -> None: await client.sync_timeout_height() # load account - private_key_in_hexa = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() @@ -30,7 +36,6 @@ async def main() -> None: # prepare tx msg market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) diff --git a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py b/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py index b46ca371..2f67f6c4 100644 --- a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py +++ b/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + """For a validator to withdraw his rewards & commissions simultaneously""" # select network: local, testnet, mainnet network = Network.testnet() @@ -22,7 +27,7 @@ async def main() -> None: # load account # private key is that from the validator's wallet - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/4_MsgCreateSpotMarketOrder.py index d689362f..06a42a96 100644 --- a/examples/chain_client/4_MsgCreateSpotMarketOrder.py +++ b/examples/chain_client/4_MsgCreateSpotMarketOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/5_MsgCancelSpotOrder.py b/examples/chain_client/5_MsgCancelSpotOrder.py index a6fabc01..63167309 100644 --- a/examples/chain_client/5_MsgCancelSpotOrder.py +++ b/examples/chain_client/5_MsgCancelSpotOrder.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py index b875d339..e46f1acb 100644 --- a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/71_CreateDenom.py b/examples/chain_client/71_CreateDenom.py index 61e76dbf..0662439a 100644 --- a/examples/chain_client/71_CreateDenom.py +++ b/examples/chain_client/71_CreateDenom.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/72_MsgMint.py b/examples/chain_client/72_MsgMint.py index e96bad93..d38449be 100644 --- a/examples/chain_client/72_MsgMint.py +++ b/examples/chain_client/72_MsgMint.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/73_MsgBurn.py b/examples/chain_client/73_MsgBurn.py index cff5a1b4..441f4ee8 100644 --- a/examples/chain_client/73_MsgBurn.py +++ b/examples/chain_client/73_MsgBurn.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/74_MsgSetDenomMetadata.py b/examples/chain_client/74_MsgSetDenomMetadata.py index 58fa30c0..367649e0 100644 --- a/examples/chain_client/74_MsgSetDenomMetadata.py +++ b/examples/chain_client/74_MsgSetDenomMetadata.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( network=network, diff --git a/examples/chain_client/75_MsgChangeAdmin.py b/examples/chain_client/75_MsgChangeAdmin.py index 2abc6ec6..d1a1ba46 100644 --- a/examples/chain_client/75_MsgChangeAdmin.py +++ b/examples/chain_client/75_MsgChangeAdmin.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( network=network, diff --git a/examples/chain_client/76_MsgExecuteContractCompat.py b/examples/chain_client/76_MsgExecuteContractCompat.py index 978ff115..892c125f 100644 --- a/examples/chain_client/76_MsgExecuteContractCompat.py +++ b/examples/chain_client/76_MsgExecuteContractCompat.py @@ -1,6 +1,8 @@ import asyncio import json +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/77_MsgLiquidatePosition.py b/examples/chain_client/77_MsgLiquidatePosition.py index 65e7f12b..6dcbacfb 100644 --- a/examples/chain_client/77_MsgLiquidatePosition.py +++ b/examples/chain_client/77_MsgLiquidatePosition.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py index 744b5ff9..e7e06c62 100644 --- a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py +++ b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/8_MsgCancelDerivativeOrder.py b/examples/chain_client/8_MsgCancelDerivativeOrder.py index b784b536..6a59167a 100644 --- a/examples/chain_client/8_MsgCancelDerivativeOrder.py +++ b/examples/chain_client/8_MsgCancelDerivativeOrder.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/poetry.lock b/poetry.lock index 9d754939..72bd53e3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1395,13 +1395,13 @@ test = ["eth-utils (>=1.0.1,<3)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>= [[package]] name = "identify" -version = "2.5.34" +version = "2.5.33" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.34-py2.py3-none-any.whl", hash = "sha256:a4316013779e433d08b96e5eabb7f641e6c7942e4ab5d4c509ebd2e7a8994aed"}, - {file = "identify-2.5.34.tar.gz", hash = "sha256:ee17bc9d499899bc9eaec1ac7bf2dc9eedd480db9d88b96d123d3b64a9d34f5d"}, + {file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"}, + {file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"}, ] [package.extras] @@ -1785,13 +1785,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.6.1" +version = "3.6.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" files = [ - {file = "pre_commit-3.6.1-py2.py3-none-any.whl", hash = "sha256:9fe989afcf095d2c4796ce7c553cf28d4d4a9b9346de3cda079bcf40748454a4"}, - {file = "pre_commit-3.6.1.tar.gz", hash = "sha256:c90961d8aa706f75d60935aba09469a6b0bcb8345f127c3fbee4bdc5f114cf4b"}, + {file = "pre_commit-3.6.0-py2.py3-none-any.whl", hash = "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376"}, + {file = "pre_commit-3.6.0.tar.gz", hash = "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d"}, ] [package.dependencies] @@ -1912,13 +1912,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" -version = "8.0.0" +version = "7.4.4" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"}, - {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"}, + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, ] [package.dependencies] @@ -1926,7 +1926,7 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=1.3.0,<2.0" +pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] @@ -1934,17 +1934,17 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no [[package]] name = "pytest-asyncio" -version = "0.23.5" +version = "0.23.4" description = "Pytest support for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-asyncio-0.23.5.tar.gz", hash = "sha256:3a048872a9c4ba14c3e90cc1aa20cbc2def7d01c7c8db3777ec281ba9c057675"}, - {file = "pytest_asyncio-0.23.5-py3-none-any.whl", hash = "sha256:4e7093259ba018d58ede7d5315131d21923a60f8a6e9ee266ce1589685c89eac"}, + {file = "pytest-asyncio-0.23.4.tar.gz", hash = "sha256:2143d9d9375bf372a73260e4114541485e84fca350b0b6b92674ca56ff5f7ea2"}, + {file = "pytest_asyncio-0.23.4-py3-none-any.whl", hash = "sha256:b0079dfac14b60cd1ce4691fbfb1748fe939db7d0234b5aba97197d10fbe0fef"}, ] [package.dependencies] -pytest = ">=7.0.0,<9" +pytest = ">=7.0.0,<8" [package.extras] docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] @@ -1982,6 +1982,20 @@ files = [ [package.dependencies] pytest = ">=3.6.0" +[[package]] +name = "python-dotenv" +version = "1.0.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "pyunormalize" version = "15.1.0" @@ -2371,18 +2385,18 @@ files = [ [[package]] name = "setuptools" -version = "69.1.0" +version = "69.0.3" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"}, - {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"}, + {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, + {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] @@ -2698,4 +2712,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "7d6d14d38c3b61b57e268c236168e21a1b90e7fa0e36814a44468cace4f699a1" +content-hash = "9e0468421485c45e3ce0e68578905dac1e50a1ed1cae8f8c6a19c91b67f36ca0" diff --git a/pyinjective/denoms_devnet.ini b/pyinjective/denoms_devnet.ini index 62979d72..3c422179 100644 --- a/pyinjective/denoms_devnet.ini +++ b/pyinjective/denoms_devnet.ini @@ -169,6 +169,15 @@ min_display_price_tick_size = 0.001 min_quantity_tick_size = 10000000000000 min_display_quantity_tick_size = 0.00001 +[0x2d3b8d8833dda54a717adea9119134556848105fd6028e9a4a526e4e5a122a57] +description = 'Devnet Spot KIRA/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000 +min_display_quantity_tick_size = 1000 + [0x1422a13427d5eabd4d8de7907c8340f7e58cb15553a9fd4ad5c90406561886f9] description = 'Devnet Derivative COMP/USDT PERP' base = 0 @@ -291,6 +300,10 @@ decimals = 18 peggy_denom = inj decimals = 18 +[KIRA] +peggy_denom = factory/inj1xy3kvlr4q4wdd6lrelsrw2fk2ged0any44hhwq/KIRA +decimals = 6 + [LINK] peggy_denom = peggy0x514910771AF9Ca656af840dff83E8264EcF986CA decimals = 18 diff --git a/pyinjective/denoms_mainnet.ini b/pyinjective/denoms_mainnet.ini index b2430837..9d88ca6d 100644 --- a/pyinjective/denoms_mainnet.ini +++ b/pyinjective/denoms_mainnet.ini @@ -682,6 +682,24 @@ min_display_price_tick_size = 0.000001 min_quantity_tick_size = 10000000000000000000 min_display_quantity_tick_size = 10 +[0x0a1366c8b05658c0ccca6064e4b20aacd5ad350c02debd6ec0f4dc9178145d14] +description = 'Mainnet Spot GYEN/USDT' +base = 6 +quote = 6 +min_price_tick_size = 0.000001 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 100000000 +min_display_quantity_tick_size = 100 + +[0x9c8a91a894f773792b1e8d0b6a8224a6b748753738e9945020ee566266f817be] +description = 'Mainnet Spot USDCnb/USDT' +base = 6 +quote = 6 +min_price_tick_size = 0.0001 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 100000 +min_display_quantity_tick_size = 0.1 + [0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce] description = 'Mainnet Derivative BTC/USDT PERP' base = 0 @@ -736,14 +754,23 @@ min_display_price_tick_size = 0.001 min_quantity_tick_size = 0.01 min_display_quantity_tick_size = 0.01 +[0xcf18525b53e54ad7d27477426ade06d69d8d56d2f3bf35fe5ce2ad9eb97c2fbc] +description = 'Mainnet Derivative OSMO/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + [0x06c5a306492ddc2b8dc56969766959163287ed68a6b59baa2f42330dda0aebe0] description = 'Mainnet Derivative SOL/USDT PERP' base = 0 quote = 6 min_price_tick_size = 10000 min_display_price_tick_size = 0.01 -min_quantity_tick_size = 0.1 -min_display_quantity_tick_size = 0.1 +min_quantity_tick_size = 0.001 +min_display_quantity_tick_size = 0.001 [0xcd0c859a99f26bb3530e21890937ed77d20754aa7825a599c71710514fc125ef] description = 'Mainnet Derivative 1MPEPE/USDT PERP' @@ -817,6 +844,51 @@ min_display_price_tick_size = 0.00001 min_quantity_tick_size = 1 min_display_quantity_tick_size = 1 +[0x30a1463cfb4c393c80e257ab93118cecd73c1e632dc4d2d31c12a51bc0a70bd7] +description = 'Mainnet Derivative AVAX/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.01 +min_quantity_tick_size = 0.01 +min_display_quantity_tick_size = 0.01 + +[0x18b2ca44b3d20a3b87c87d3765669b09b73b5e900693896c08394c70e79ab1e7] +description = 'Mainnet Derivative SUI/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + +[0x1a6d3a59f45904e0a4a2eed269fc2f552e7e407ac90aaaeb602c31b017573f88] +description = 'Mainnet Derivative WIF/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 100 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1 +min_display_quantity_tick_size = 1 + +[0x48fcecd66ebabbf5a331178ec693b261dfae66ddfe6f552d7446744c6e78046c] +description = 'Mainnet Derivative OP/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + +[0x6ddf0b8fbbd888981aafdae9fc967a12c6777aac4dd100a8257b8755c0c4b7d5] +description = 'Mainnet Derivative ARB/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + [AAVE] peggy_denom = peggy0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9 decimals = 18 @@ -845,6 +917,10 @@ decimals = 6 peggy_denom = peggy0xBB0E17EF65F82Ab018d8EDd776e8DD940327B28b decimals = 18 +[Axelar Wrapped USDC] +peggy_denom = ibc/7E1AF94AD246BE522892751046F0C959B768642E5671CC3742264068D49553C0 +decimals = 6 + [BRETT] peggy_denom = factory/inj13jjdsa953w03dvecsr43dj5r6a2vzt7n0spncv/brett decimals = 6 @@ -885,6 +961,10 @@ decimals = 6 peggy_denom = peggy0xc944E90C64B2c07662A292be6244BDf05Cda44a7 decimals = 18 +[GYEN] +peggy_denom = peggy0xC08512927D12348F6620a698105e1BAac6EcD911 +decimals = 6 + [HUAHUA] peggy_denom = ibc/E7807A46C0B7B44B350DA58F51F278881B863EC4DCA94635DAB39E52C30766CB decimals = 6 @@ -933,6 +1013,10 @@ decimals = 18 peggy_denom = factory/inj1xtel2knkt8hmc9dnzpjz6kdmacgcfmlv5f308w/ninja decimals = 6 +[Noble USD Coin] +peggy_denom = ibc/2CBC2EA121AE42563B08028466F37B600F2D7D4282342DE938283CC3FB2BC00E +decimals = 6 + [ORAI] peggy_denom = ibc/C20C0A822BD22B2CEF0D067400FCCFB6FAEEE9E91D360B4E0725BD522302D565 decimals = 6 @@ -973,14 +1057,6 @@ decimals = 6 peggy_denom = peggy0x6B3595068778DD592e39A122f4f5a5cF09C90fE2 decimals = 18 -[SteadyBTC] -peggy_denom = peggy0x4986fD36b6b16f49b43282Ee2e24C5cF90ed166d -decimals = 18 - -[SteadyETH] -peggy_denom = peggy0x3F07A84eCdf494310D397d24c1C78B041D2fa622 -decimals = 18 - [TALIS] peggy_denom = factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis decimals = 6 @@ -997,12 +1073,12 @@ decimals = 18 peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj1q6zlut7gtkzknkk773jecujwsdkgq882akqksk decimals = 6 -[USDC] -peggy_denom = peggy0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 +[USD Coin (Wormhole from Solana)] +peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj12pwnhtv7yat2s30xuf4gdk9qm85v4j3e60dgvu decimals = 6 -[USDCso] -peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj12pwnhtv7yat2s30xuf4gdk9qm85v4j3e60dgvu +[USDC] +peggy_denom = peggy0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 decimals = 6 [USDT] @@ -1049,10 +1125,6 @@ decimals = 6 peggy_denom = peggy0xb2617246d0c6c0087f18703d576831899ca94f01 decimals = 18 -[axlUSDC] -peggy_denom = ibc/7E1AF94AD246BE522892751046F0C959B768642E5671CC3742264068D49553C0 -decimals = 6 - [nINJ] peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj13xlpypcwl5fuc84uhqzzqumnrcfpptyl6w3vrf decimals = 18 @@ -1060,3 +1132,11 @@ decimals = 18 [stINJ] peggy_denom = ibc/AC87717EA002B0123B10A05063E69BCA274BA2C44D842AEEB41558D2856DCE93 decimals = 18 + +[steadyBTC] +peggy_denom = peggy0x4986fD36b6b16f49b43282Ee2e24C5cF90ed166d +decimals = 18 + +[steadyETH] +peggy_denom = peggy0x3F07A84eCdf494310D397d24c1C78B041D2fa622 +decimals = 18 diff --git a/pyinjective/denoms_testnet.ini b/pyinjective/denoms_testnet.ini index d81212d8..fd823592 100644 --- a/pyinjective/denoms_testnet.ini +++ b/pyinjective/denoms_testnet.ini @@ -397,7 +397,7 @@ decimals = 8 peggy_denom = inj decimals = 18 -[MITOTEST1] +[MitoTest1] peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/mitotest1 decimals = 18 diff --git a/pyproject.toml b/pyproject.toml index 6b7d593e..0838ac19 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ websockets = "*" web3 = "^6.0" [tool.poetry.group.test.dependencies] -pytest = "*" +pytest = "<8" pytest-asyncio = "*" pytest-grpc = "*" requests-mock = "*" @@ -51,6 +51,7 @@ pre-commit = "^3.4.0" flakeheaven = "^3.3.0" isort = "^5.12.0" black = "^23.9.1" +python-dotenv = "^1.0.1" [tool.flakeheaven] From 90f66bd53d8ded178032f36029ab888ce62fe5b9 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 16 Jan 2024 11:52:25 -0300 Subject: [PATCH 12/44] (fix) Changed version number for dev branch --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0838ac19..c983dd07 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ websockets = "*" web3 = "^6.0" [tool.poetry.group.test.dependencies] -pytest = "<8" +pytest = "*" pytest-asyncio = "*" pytest-grpc = "*" requests-mock = "*" From 9c1b774b75d302964c4c22a2ec6ddd6d8d320d25 Mon Sep 17 00:00:00 2001 From: abel Date: Mon, 12 Feb 2024 17:32:02 -0300 Subject: [PATCH 13/44] (fix) Updated dependencies versions in poetry.lock --- poetry.lock | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/poetry.lock b/poetry.lock index 72bd53e3..082dfb36 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1395,13 +1395,13 @@ test = ["eth-utils (>=1.0.1,<3)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>= [[package]] name = "identify" -version = "2.5.33" +version = "2.5.34" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"}, - {file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"}, + {file = "identify-2.5.34-py2.py3-none-any.whl", hash = "sha256:a4316013779e433d08b96e5eabb7f641e6c7942e4ab5d4c509ebd2e7a8994aed"}, + {file = "identify-2.5.34.tar.gz", hash = "sha256:ee17bc9d499899bc9eaec1ac7bf2dc9eedd480db9d88b96d123d3b64a9d34f5d"}, ] [package.extras] @@ -1785,13 +1785,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.6.0" +version = "3.6.1" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" files = [ - {file = "pre_commit-3.6.0-py2.py3-none-any.whl", hash = "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376"}, - {file = "pre_commit-3.6.0.tar.gz", hash = "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d"}, + {file = "pre_commit-3.6.1-py2.py3-none-any.whl", hash = "sha256:9fe989afcf095d2c4796ce7c553cf28d4d4a9b9346de3cda079bcf40748454a4"}, + {file = "pre_commit-3.6.1.tar.gz", hash = "sha256:c90961d8aa706f75d60935aba09469a6b0bcb8345f127c3fbee4bdc5f114cf4b"}, ] [package.dependencies] @@ -1912,13 +1912,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" -version = "7.4.4" +version = "8.0.0" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, + {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"}, + {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"}, ] [package.dependencies] @@ -1926,7 +1926,7 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" +pluggy = ">=1.3.0,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] @@ -1934,17 +1934,17 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no [[package]] name = "pytest-asyncio" -version = "0.23.4" +version = "0.23.5" description = "Pytest support for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-asyncio-0.23.4.tar.gz", hash = "sha256:2143d9d9375bf372a73260e4114541485e84fca350b0b6b92674ca56ff5f7ea2"}, - {file = "pytest_asyncio-0.23.4-py3-none-any.whl", hash = "sha256:b0079dfac14b60cd1ce4691fbfb1748fe939db7d0234b5aba97197d10fbe0fef"}, + {file = "pytest-asyncio-0.23.5.tar.gz", hash = "sha256:3a048872a9c4ba14c3e90cc1aa20cbc2def7d01c7c8db3777ec281ba9c057675"}, + {file = "pytest_asyncio-0.23.5-py3-none-any.whl", hash = "sha256:4e7093259ba018d58ede7d5315131d21923a60f8a6e9ee266ce1589685c89eac"}, ] [package.dependencies] -pytest = ">=7.0.0,<8" +pytest = ">=7.0.0,<9" [package.extras] docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] @@ -2385,18 +2385,18 @@ files = [ [[package]] name = "setuptools" -version = "69.0.3" +version = "69.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, - {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, + {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"}, + {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] @@ -2712,4 +2712,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "9e0468421485c45e3ce0e68578905dac1e50a1ed1cae8f8c6a19c91b67f36ca0" +content-hash = "531c4e91b09feb8097149a63a8cfde93152cd904df0f6616790d51ca8838dfe0" From 13f776d5e7a4aa33f6978e3ecb20e3dd3cb36242 Mon Sep 17 00:00:00 2001 From: abel Date: Mon, 12 Feb 2024 17:37:49 -0300 Subject: [PATCH 14/44] (fix) Fixed typo in CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21bbaca6..a6094ec5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. -## [1.2.0] - 2024-02-12 +## [1.3.0] - 2024-02-12 ### Changed - Removed `asyncio` from the dependencies From 65e6e999ddce56dc18ea7c599e1ef6e3c36d191b Mon Sep 17 00:00:00 2001 From: abel Date: Fri, 9 Feb 2024 00:14:58 -0300 Subject: [PATCH 15/44] (feat) Added support for all `distribution` module queries. Added also new example scripts for all queries and unit tests --- .../1_ValidatorDistributionInfo.py | 16 + .../2_ValidatorOutstandingRewards.py | 16 + .../distribution/3_ValidatorCommission.py | 16 + .../distribution/4_ValidatorSlashes.py | 20 ++ .../distribution/5_DelegationRewards.py | 19 + .../distribution/6_DelegationTotalRewards.py | 18 + .../distribution/7_DelegatorValidators.py | 18 + .../8_DelegatorWithdrawAddress.py | 18 + .../distribution/9_CommunityPool.py | 15 + pyinjective/async_client.py | 67 ++++ .../chain/grpc/chain_grpc_distribution_api.py | 109 ++++++ ...y => configurable_authz_query_servicer.py} | 0 ...onfigurable_distribution_query_servicer.py | 69 ++++ .../grpc/test_chain_grpc_distribution_api.py | 338 ++++++++++++++++++ 14 files changed, 739 insertions(+) create mode 100644 examples/chain_client/distribution/1_ValidatorDistributionInfo.py create mode 100644 examples/chain_client/distribution/2_ValidatorOutstandingRewards.py create mode 100644 examples/chain_client/distribution/3_ValidatorCommission.py create mode 100644 examples/chain_client/distribution/4_ValidatorSlashes.py create mode 100644 examples/chain_client/distribution/5_DelegationRewards.py create mode 100644 examples/chain_client/distribution/6_DelegationTotalRewards.py create mode 100644 examples/chain_client/distribution/7_DelegatorValidators.py create mode 100644 examples/chain_client/distribution/8_DelegatorWithdrawAddress.py create mode 100644 examples/chain_client/distribution/9_CommunityPool.py create mode 100644 pyinjective/client/chain/grpc/chain_grpc_distribution_api.py rename tests/client/chain/grpc/{configurable_autz_query_servicer.py => configurable_authz_query_servicer.py} (100%) create mode 100644 tests/client/chain/grpc/configurable_distribution_query_servicer.py create mode 100644 tests/client/chain/grpc/test_chain_grpc_distribution_api.py diff --git a/examples/chain_client/distribution/1_ValidatorDistributionInfo.py b/examples/chain_client/distribution/1_ValidatorDistributionInfo.py new file mode 100644 index 00000000..13161630 --- /dev/null +++ b/examples/chain_client/distribution/1_ValidatorDistributionInfo.py @@ -0,0 +1,16 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + distribution_info = await client.fetch_validator_distribution_info(validator_address=validator_address) + print(distribution_info) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/2_ValidatorOutstandingRewards.py b/examples/chain_client/distribution/2_ValidatorOutstandingRewards.py new file mode 100644 index 00000000..31833682 --- /dev/null +++ b/examples/chain_client/distribution/2_ValidatorOutstandingRewards.py @@ -0,0 +1,16 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + rewards = await client.fetch_validator_outstanding_rewards(validator_address=validator_address) + print(rewards) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/3_ValidatorCommission.py b/examples/chain_client/distribution/3_ValidatorCommission.py new file mode 100644 index 00000000..a82e191b --- /dev/null +++ b/examples/chain_client/distribution/3_ValidatorCommission.py @@ -0,0 +1,16 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + commission = await client.fetch_validator_commission(validator_address=validator_address) + print(commission) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/4_ValidatorSlashes.py b/examples/chain_client/distribution/4_ValidatorSlashes.py new file mode 100644 index 00000000..08dbfea1 --- /dev/null +++ b/examples/chain_client/distribution/4_ValidatorSlashes.py @@ -0,0 +1,20 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + limit = 2 + pagination = PaginationOption(limit=limit) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + contracts = await client.fetch_validator_slashes(validator_address=validator_address, pagination=pagination) + print(contracts) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/5_DelegationRewards.py b/examples/chain_client/distribution/5_DelegationRewards.py new file mode 100644 index 00000000..da112263 --- /dev/null +++ b/examples/chain_client/distribution/5_DelegationRewards.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + validator_address = "injvaloper156t3yxd4udv0h9gwagfcmwnmm3quy0nph7tyh5" + rewards = await client.fetch_delegation_rewards( + delegator_address=delegator_address, validator_address=validator_address + ) + print(rewards) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/6_DelegationTotalRewards.py b/examples/chain_client/distribution/6_DelegationTotalRewards.py new file mode 100644 index 00000000..c67dc94f --- /dev/null +++ b/examples/chain_client/distribution/6_DelegationTotalRewards.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + rewards = await client.fetch_delegation_total_rewards( + delegator_address=delegator_address, + ) + print(rewards) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/7_DelegatorValidators.py b/examples/chain_client/distribution/7_DelegatorValidators.py new file mode 100644 index 00000000..f03fb8ec --- /dev/null +++ b/examples/chain_client/distribution/7_DelegatorValidators.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + validators = await client.fetch_delegator_validators( + delegator_address=delegator_address, + ) + print(validators) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/8_DelegatorWithdrawAddress.py b/examples/chain_client/distribution/8_DelegatorWithdrawAddress.py new file mode 100644 index 00000000..d3c27091 --- /dev/null +++ b/examples/chain_client/distribution/8_DelegatorWithdrawAddress.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + withdraw_address = await client.fetch_delegator_withdraw_address( + delegator_address=delegator_address, + ) + print(withdraw_address) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/9_CommunityPool.py b/examples/chain_client/distribution/9_CommunityPool.py new file mode 100644 index 00000000..7a803d03 --- /dev/null +++ b/examples/chain_client/distribution/9_CommunityPool.py @@ -0,0 +1,15 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + community_pool = await client.fetch_community_pool() + print(community_pool) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index e8da821b..dea12f12 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -12,6 +12,7 @@ from pyinjective.client.chain.grpc.chain_grpc_auth_api import ChainGrpcAuthApi from pyinjective.client.chain.grpc.chain_grpc_authz_api import ChainGrpcAuthZApi from pyinjective.client.chain.grpc.chain_grpc_bank_api import ChainGrpcBankApi +from pyinjective.client.chain.grpc.chain_grpc_distribution_api import ChainGrpcDistributionApi from pyinjective.client.chain.grpc.chain_grpc_token_factory_api import ChainGrpcTokenFactoryApi from pyinjective.client.chain.grpc.chain_grpc_wasm_api import ChainGrpcWasmApi from pyinjective.client.chain.grpc_stream.chain_grpc_chain_stream import ChainGrpcChainStream @@ -178,6 +179,12 @@ def __init__( metadata_query_provider=self._chain_cookie_metadata_requestor ), ) + self.distribution_api = ChainGrpcDistributionApi( + channel=self.chain_channel, + metadata_provider=lambda: self.network.chain_metadata( + metadata_query_provider=self._chain_cookie_metadata_requestor + ), + ) self.token_factory_api = ChainGrpcTokenFactoryApi( channel=self.chain_channel, metadata_provider=lambda: self.network.chain_metadata( @@ -572,6 +579,66 @@ async def fetch_send_enabled( ) -> Dict[str, Any]: return await self.bank_api.fetch_send_enabled(denoms=denoms, pagination=pagination) + async def fetch_validator_distribution_info(self, validator_address: str) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_distribution_info(validator_address=validator_address) + + async def fetch_validator_outstanding_rewards(self, validator_address: str) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_outstanding_rewards(validator_address=validator_address) + + async def fetch_validator_commission(self, validator_address: str) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_commission(validator_address=validator_address) + + async def fetch_validator_slashes( + self, + validator_address: str, + starting_height: Optional[int] = None, + ending_height: Optional[int] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_slashes( + validator_address=validator_address, + starting_height=starting_height, + ending_height=ending_height, + pagination=pagination, + ) + + async def fetch_delegation_rewards( + self, + delegator_address: str, + validator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegation_rewards( + delegator_address=delegator_address, + validator_address=validator_address, + ) + + async def fetch_delegation_total_rewards( + self, + delegator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegation_total_rewards( + delegator_address=delegator_address, + ) + + async def fetch_delegator_validators( + self, + delegator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegator_validators( + delegator_address=delegator_address, + ) + + async def fetch_delegator_withdraw_address( + self, + delegator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegator_withdraw_address( + delegator_address=delegator_address, + ) + + async def fetch_community_pool(self) -> Dict[str, Any]: + return await self.distribution_api.fetch_community_pool() + # Injective Exchange client methods # Auction RPC diff --git a/pyinjective/client/chain/grpc/chain_grpc_distribution_api.py b/pyinjective/client/chain/grpc/chain_grpc_distribution_api.py new file mode 100644 index 00000000..e7da0966 --- /dev/null +++ b/pyinjective/client/chain/grpc/chain_grpc_distribution_api.py @@ -0,0 +1,109 @@ +from typing import Any, Callable, Dict, Optional + +from grpc.aio import Channel + +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + query_pb2 as distribution_query_pb, + query_pb2_grpc as distribution_query_grpc, +) +from pyinjective.utils.grpc_api_request_assistant import GrpcApiRequestAssistant + + +class ChainGrpcDistributionApi: + def __init__(self, channel: Channel, metadata_provider: Callable): + self._stub = distribution_query_grpc.QueryStub(channel) + self._assistant = GrpcApiRequestAssistant(metadata_provider=metadata_provider) + + async def fetch_module_params(self) -> Dict[str, Any]: + request = distribution_query_pb.QueryParamsRequest() + response = await self._execute_call(call=self._stub.Params, request=request) + + return response + + async def fetch_validator_distribution_info(self, validator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryValidatorDistributionInfoRequest(validator_address=validator_address) + response = await self._execute_call(call=self._stub.ValidatorDistributionInfo, request=request) + + return response + + async def fetch_validator_outstanding_rewards(self, validator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryValidatorOutstandingRewardsRequest(validator_address=validator_address) + response = await self._execute_call(call=self._stub.ValidatorOutstandingRewards, request=request) + + return response + + async def fetch_validator_commission(self, validator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryValidatorCommissionRequest(validator_address=validator_address) + response = await self._execute_call(call=self._stub.ValidatorCommission, request=request) + + return response + + async def fetch_validator_slashes( + self, + validator_address: str, + starting_height: Optional[int] = None, + ending_height: Optional[int] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + pagination_request = None + if pagination is not None: + pagination_request = pagination.create_pagination_request() + request = distribution_query_pb.QueryValidatorSlashesRequest( + validator_address=validator_address, + starting_height=starting_height, + ending_height=ending_height, + pagination=pagination_request, + ) + response = await self._execute_call(call=self._stub.ValidatorSlashes, request=request) + + return response + + async def fetch_delegation_rewards( + self, + delegator_address: str, + validator_address: str, + ) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegationRewardsRequest( + delegator_address=delegator_address, + validator_address=validator_address, + ) + response = await self._execute_call(call=self._stub.DelegationRewards, request=request) + + return response + + async def fetch_delegation_total_rewards( + self, + delegator_address: str, + ) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegationTotalRewardsRequest( + delegator_address=delegator_address, + ) + response = await self._execute_call(call=self._stub.DelegationTotalRewards, request=request) + + return response + + async def fetch_delegator_validators(self, delegator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegatorValidatorsRequest( + delegator_address=delegator_address, + ) + response = await self._execute_call(call=self._stub.DelegatorValidators, request=request) + + return response + + async def fetch_delegator_withdraw_address(self, delegator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegatorWithdrawAddressRequest( + delegator_address=delegator_address, + ) + response = await self._execute_call(call=self._stub.DelegatorWithdrawAddress, request=request) + + return response + + async def fetch_community_pool(self) -> Dict[str, Any]: + request = distribution_query_pb.QueryCommunityPoolRequest() + response = await self._execute_call(call=self._stub.CommunityPool, request=request) + + return response + + async def _execute_call(self, call: Callable, request) -> Dict[str, Any]: + return await self._assistant.execute_call(call=call, request=request) diff --git a/tests/client/chain/grpc/configurable_autz_query_servicer.py b/tests/client/chain/grpc/configurable_authz_query_servicer.py similarity index 100% rename from tests/client/chain/grpc/configurable_autz_query_servicer.py rename to tests/client/chain/grpc/configurable_authz_query_servicer.py diff --git a/tests/client/chain/grpc/configurable_distribution_query_servicer.py b/tests/client/chain/grpc/configurable_distribution_query_servicer.py new file mode 100644 index 00000000..d2e1d7da --- /dev/null +++ b/tests/client/chain/grpc/configurable_distribution_query_servicer.py @@ -0,0 +1,69 @@ +from collections import deque + +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + query_pb2 as distribution_query_pb, + query_pb2_grpc as distribution_query_grpc, +) + + +class ConfigurableDistributionQueryServicer(distribution_query_grpc.QueryServicer): + def __init__(self): + super().__init__() + self.distribution_params = deque() + self.validator_distribution_info_responses = deque() + self.validator_outstanding_rewards_responses = deque() + self.validator_commission_responses = deque() + self.validator_slashes_responses = deque() + self.delegation_rewards_responses = deque() + self.delegation_total_rewards_responses = deque() + self.delegator_validators_responses = deque() + self.delegator_withdraw_address_responses = deque() + self.community_pool_responses = deque() + + async def Params(self, request: distribution_query_pb.QueryParamsRequest, context=None, metadata=None): + return self.distribution_params.pop() + + async def ValidatorDistributionInfo( + self, request: distribution_query_pb.QueryValidatorDistributionInfoRequest, context=None, metadata=None + ): + return self.validator_distribution_info_responses.pop() + + async def ValidatorOutstandingRewards( + self, request: distribution_query_pb.QueryValidatorOutstandingRewardsRequest, context=None, metadata=None + ): + return self.validator_outstanding_rewards_responses.pop() + + async def ValidatorCommission( + self, request: distribution_query_pb.QueryValidatorCommissionRequest, context=None, metadata=None + ): + return self.validator_commission_responses.pop() + + async def ValidatorSlashes( + self, request: distribution_query_pb.QueryValidatorSlashesRequest, context=None, metadata=None + ): + return self.validator_slashes_responses.pop() + + async def DelegationRewards( + self, request: distribution_query_pb.QueryDelegationRewardsRequest, context=None, metadata=None + ): + return self.delegation_rewards_responses.pop() + + async def DelegationTotalRewards( + self, request: distribution_query_pb.QueryDelegationTotalRewardsRequest, context=None, metadata=None + ): + return self.delegation_total_rewards_responses.pop() + + async def DelegatorValidators( + self, request: distribution_query_pb.QueryDelegatorValidatorsRequest, context=None, metadata=None + ): + return self.delegator_validators_responses.pop() + + async def DelegatorWithdrawAddress( + self, request: distribution_query_pb.QueryDelegatorWithdrawAddressRequest, context=None, metadata=None + ): + return self.delegator_withdraw_address_responses.pop() + + async def CommunityPool( + self, request: distribution_query_pb.QueryCommunityPoolRequest, context=None, metadata=None + ): + return self.community_pool_responses.pop() diff --git a/tests/client/chain/grpc/test_chain_grpc_distribution_api.py b/tests/client/chain/grpc/test_chain_grpc_distribution_api.py new file mode 100644 index 00000000..9f8ee9a6 --- /dev/null +++ b/tests/client/chain/grpc/test_chain_grpc_distribution_api.py @@ -0,0 +1,338 @@ +import base64 + +import grpc +import pytest + +from pyinjective.client.chain.grpc.chain_grpc_distribution_api import ChainGrpcDistributionApi +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network +from pyinjective.proto.cosmos.base.query.v1beta1 import pagination_pb2 as pagination_pb +from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as coin_pb +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + distribution_pb2 as distribution_pb, + query_pb2 as distribution_query_pb, +) +from tests.client.chain.grpc.configurable_distribution_query_servicer import ConfigurableDistributionQueryServicer + + +@pytest.fixture +def distribution_servicer(): + return ConfigurableDistributionQueryServicer() + + +class TestChainGrpcAuthApi: + @pytest.mark.asyncio + async def test_fetch_module_params( + self, + distribution_servicer, + ): + params = distribution_pb.Params( + community_tax="0.050000000000000000", + base_proposer_reward="0.060000000000000000", + bonus_proposer_reward="0.070000000000000000", + withdraw_addr_enabled=True, + ) + + distribution_servicer.distribution_params.append(distribution_query_pb.QueryParamsResponse(params=params)) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + module_params = await api.fetch_module_params() + expected_params = { + "params": { + "communityTax": params.community_tax, + "baseProposerReward": params.base_proposer_reward, + "bonusProposerReward": params.bonus_proposer_reward, + "withdrawAddrEnabled": params.withdraw_addr_enabled, + } + } + + assert expected_params == module_params + + @pytest.mark.asyncio + async def test_fetch_validator_distribution_info( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + commission = coin_pb.DecCoin(denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", amount="54497408") + + distribution_servicer.validator_distribution_info_responses.append( + distribution_query_pb.QueryValidatorDistributionInfoResponse( + operator_address=operator, self_bond_rewards=[reward], commission=[commission] + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + validator_info = await api.fetch_validator_distribution_info(validator_address=operator) + expected_info = { + "operatorAddress": operator, + "selfBondRewards": [{"denom": reward.denom, "amount": reward.amount}], + "commission": [{"denom": commission.denom, "amount": commission.amount}], + } + + assert expected_info == validator_info + + @pytest.mark.asyncio + async def test_fetch_validator_outstanding_rewards( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + rewards = distribution_pb.ValidatorOutstandingRewards(rewards=[reward]) + + distribution_servicer.validator_outstanding_rewards_responses.append( + distribution_query_pb.QueryValidatorOutstandingRewardsResponse( + rewards=rewards, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + validator_rewards = await api.fetch_validator_outstanding_rewards(validator_address=operator) + expected_rewards = {"rewards": {"rewards": [{"denom": reward.denom, "amount": reward.amount}]}} + + assert expected_rewards == validator_rewards + + @pytest.mark.asyncio + async def test_fetch_validator_commission( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + first_commission = coin_pb.DecCoin(denom="inj", amount="1000000000") + commission = distribution_pb.ValidatorAccumulatedCommission(commission=[first_commission]) + + distribution_servicer.validator_commission_responses.append( + distribution_query_pb.QueryValidatorCommissionResponse( + commission=commission, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + commission = await api.fetch_validator_commission(validator_address=operator) + expected_commission = { + "commission": {"commission": [{"denom": first_commission.denom, "amount": first_commission.amount}]} + } + + assert expected_commission == commission + + @pytest.mark.asyncio + async def test_fetch_validator_slashes( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + slash = distribution_pb.ValidatorSlashEvent( + validator_period=1, + fraction="4", + ) + pagination = pagination_pb.PageResponse(total=2) + + distribution_servicer.validator_slashes_responses.append( + distribution_query_pb.QueryValidatorSlashesResponse( + slashes=[slash], + pagination=pagination, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + slashes = await api.fetch_validator_slashes( + validator_address=operator, + starting_height=20, + ending_height=100, + pagination=PaginationOption( + skip=0, + limit=100, + ), + ) + expected_slashes = { + "slashes": [ + { + "validatorPeriod": str(slash.validator_period), + "fraction": slash.fraction, + } + ], + "pagination": {"nextKey": base64.b64encode(pagination.next_key).decode(), "total": str(pagination.total)}, + } + + assert slashes == expected_slashes + + @pytest.mark.asyncio + async def test_fetch_delegation_rewards( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + validator = "injvaloper16gdnrnl224ylje5z9vd0vn0msym7p58f00qauj" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + + distribution_servicer.delegation_rewards_responses.append( + distribution_query_pb.QueryDelegationRewardsResponse( + rewards=[reward], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + rewards = await api.fetch_delegation_rewards( + delegator_address=delegator, + validator_address=validator, + ) + expected_rewards = {"rewards": [{"denom": reward.denom, "amount": reward.amount}]} + + assert rewards == expected_rewards + + @pytest.mark.asyncio + async def test_fetch_delegation_total_rewards( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + validator = "injvaloper16gdnrnl224ylje5z9vd0vn0msym7p58f00qauj" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + delegation_delegator_reward = distribution_pb.DelegationDelegatorReward( + validator_address=validator, + reward=[reward], + ) + total = coin_pb.DecCoin(denom="inj", amount="2000000000") + + distribution_servicer.delegation_total_rewards_responses.append( + distribution_query_pb.QueryDelegationTotalRewardsResponse( + rewards=[delegation_delegator_reward], + total=[total], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + rewards = await api.fetch_delegation_total_rewards( + delegator_address=delegator, + ) + expected_rewards = { + "rewards": [ + { + "validatorAddress": validator, + "reward": [{"denom": reward.denom, "amount": reward.amount}], + } + ], + "total": [{"denom": total.denom, "amount": total.amount}], + } + + assert rewards == expected_rewards + + @pytest.mark.asyncio + async def test_fetch_delegator_validators( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + validator = "injvaloper16gdnrnl224ylje5z9vd0vn0msym7p58f00qauj" + + distribution_servicer.delegator_validators_responses.append( + distribution_query_pb.QueryDelegatorValidatorsResponse( + validators=[validator], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + validators = await api.fetch_delegator_validators( + delegator_address=delegator, + ) + expected_validators = { + "validators": [validator], + } + + assert validators == expected_validators + + @pytest.mark.asyncio + async def test_fetch_delegator_withdraw_address( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + + distribution_servicer.delegator_withdraw_address_responses.append( + distribution_query_pb.QueryDelegatorWithdrawAddressResponse( + withdraw_address=delegator, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + withdraw_address = await api.fetch_delegator_withdraw_address( + delegator_address=delegator, + ) + expected_withdraw_address = { + "withdrawAddress": delegator, + } + + assert withdraw_address == expected_withdraw_address + + @pytest.mark.asyncio + async def test_fetch_community_pool( + self, + distribution_servicer, + ): + coin = coin_pb.DecCoin(denom="inj", amount="1000000000") + distribution_servicer.community_pool_responses.append( + distribution_query_pb.QueryCommunityPoolResponse( + pool=[coin], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + community_pool = await api.fetch_community_pool() + expected_community_pool = {"pool": [{"denom": coin.denom, "amount": coin.amount}]} + + assert community_pool == expected_community_pool + + async def _dummy_metadata_provider(self): + return None From 1c1067cdea02208444e4c230e3d4976e4adc87d3 Mon Sep 17 00:00:00 2001 From: abel Date: Fri, 9 Feb 2024 00:16:59 -0300 Subject: [PATCH 16/44] (fix) Fix error due to incomplete rename --- tests/client/chain/grpc/test_chain_grpc_authz_api.py | 2 +- tests/test_async_client_deprecation_warnings.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/client/chain/grpc/test_chain_grpc_authz_api.py b/tests/client/chain/grpc/test_chain_grpc_authz_api.py index e097ff66..9d1d5586 100644 --- a/tests/client/chain/grpc/test_chain_grpc_authz_api.py +++ b/tests/client/chain/grpc/test_chain_grpc_authz_api.py @@ -7,7 +7,7 @@ from pyinjective.core.network import Network from pyinjective.proto.cosmos.authz.v1beta1 import authz_pb2, query_pb2 as authz_query from pyinjective.proto.cosmos.base.query.v1beta1 import pagination_pb2 as pagination_pb -from tests.client.chain.grpc.configurable_autz_query_servicer import ConfigurableAuthZQueryServicer +from tests.client.chain.grpc.configurable_authz_query_servicer import ConfigurableAuthZQueryServicer @pytest.fixture diff --git a/tests/test_async_client_deprecation_warnings.py b/tests/test_async_client_deprecation_warnings.py index dae2d807..1df77fe8 100644 --- a/tests/test_async_client_deprecation_warnings.py +++ b/tests/test_async_client_deprecation_warnings.py @@ -21,7 +21,7 @@ from pyinjective.proto.injective.stream.v1beta1 import query_pb2 as chain_stream_pb from pyinjective.proto.injective.types.v1beta1 import account_pb2 as account_pb from tests.client.chain.grpc.configurable_auth_query_servicer import ConfigurableAuthQueryServicer -from tests.client.chain.grpc.configurable_autz_query_servicer import ConfigurableAuthZQueryServicer +from tests.client.chain.grpc.configurable_authz_query_servicer import ConfigurableAuthZQueryServicer from tests.client.chain.grpc.configurable_bank_query_servicer import ConfigurableBankQueryServicer from tests.client.chain.stream_grpc.configurable_chain_stream_query_servicer import ConfigurableChainStreamQueryServicer from tests.client.indexer.configurable_account_query_servicer import ConfigurableAccountQueryServicer From c6c0cbd7872e6ff081551afb2c67a97744db898f Mon Sep 17 00:00:00 2001 From: abel Date: Mon, 12 Feb 2024 15:44:17 -0300 Subject: [PATCH 17/44] (feat) Added support in Composer to create all missing messages from the `distribution` module. Marked as deprecated old functions not following Python naming standards and created the replacements for them (with the correct name following standards) --- examples/chain_client/0_LocalOrderHash.py | 6 +- .../13_MsgIncreasePositionMargin.py | 2 +- examples/chain_client/15_MsgWithdraw.py | 2 +- .../chain_client/16_MsgSubaccountTransfer.py | 2 +- .../chain_client/17_MsgBatchUpdateOrders.py | 2 +- examples/chain_client/18_MsgBid.py | 2 +- examples/chain_client/19_MsgGrant.py | 2 +- examples/chain_client/1_MsgSend.py | 2 +- examples/chain_client/20_MsgExec.py | 2 +- examples/chain_client/21_MsgRevoke.py | 2 +- examples/chain_client/22_MsgSendToEth.py | 2 +- .../chain_client/23_MsgRelayPriceFeedPrice.py | 2 +- examples/chain_client/24_MsgRewardsOptOut.py | 2 +- examples/chain_client/25_MsgDelegate.py | 2 +- .../26_MsgWithdrawDelegatorReward.py | 81 ----------- examples/chain_client/2_MsgDeposit.py | 2 +- examples/chain_client/30_ExternalTransfer.py | 2 +- .../31_MsgCreateBinaryOptionsLimitOrder.py | 2 +- .../32_MsgCreateBinaryOptionsMarketOrder.py | 2 +- .../33_MsgCancelBinaryOptionsOrder.py | 2 +- .../34_MsgAdminUpdateBinaryOptionsMarket.py | 2 +- .../35_MsgInstantBinaryOptionsMarketLaunch.py | 2 +- .../chain_client/36_MsgRelayProviderPrices.py | 2 +- .../chain_client/3_MsgCreateSpotLimitOrder.py | 2 +- .../chain_client/40_MsgExecuteContract.py | 8 +- .../chain_client/41_MsgCreateInsuranceFund.py | 2 +- examples/chain_client/42_MsgUnderwrite.py | 2 +- .../chain_client/43_MsgRequestRedemption.py | 2 +- ...8_WithdrawValidatorCommissionAndRewards.py | 86 ------------ .../4_MsgCreateSpotMarketOrder.py | 2 +- examples/chain_client/5_MsgCancelSpotOrder.py | 2 +- .../6_MsgCreateDerivativeLimitOrder.py | 2 +- examples/chain_client/72_MsgMint.py | 2 +- examples/chain_client/73_MsgBurn.py | 2 +- .../76_MsgExecuteContractCompat.py | 2 +- .../chain_client/77_MsgLiquidatePosition.py | 2 +- .../7_MsgCreateDerivativeMarketOrder.py | 2 +- .../8_MsgCancelDerivativeOrder.py | 2 +- .../distribution/10_SetWithdrawAddress.py | 46 ++++++ .../11_WithdrawDelegatorReward.py | 47 +++++++ .../12_WithdrawValidatorCommission.py | 45 ++++++ .../distribution/13_FundCommunityPool.py | 47 +++++++ pyinjective/composer.py | 132 +++++++++++++----- pyinjective/core/broadcaster.py | 4 +- tests/test_composer.py | 4 +- 45 files changed, 325 insertions(+), 249 deletions(-) delete mode 100644 examples/chain_client/26_MsgWithdrawDelegatorReward.py delete mode 100644 examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py create mode 100644 examples/chain_client/distribution/10_SetWithdrawAddress.py create mode 100644 examples/chain_client/distribution/11_WithdrawDelegatorReward.py create mode 100644 examples/chain_client/distribution/12_WithdrawValidatorCommission.py create mode 100644 examples/chain_client/distribution/13_FundCommunityPool.py diff --git a/examples/chain_client/0_LocalOrderHash.py b/examples/chain_client/0_LocalOrderHash.py index a25398c6..770ad5bf 100644 --- a/examples/chain_client/0_LocalOrderHash.py +++ b/examples/chain_client/0_LocalOrderHash.py @@ -113,7 +113,7 @@ async def main() -> None: gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) @@ -150,7 +150,7 @@ async def main() -> None: gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) @@ -240,7 +240,7 @@ async def main() -> None: gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/13_MsgIncreasePositionMargin.py b/examples/chain_client/13_MsgIncreasePositionMargin.py index f54910f8..775a41e5 100644 --- a/examples/chain_client/13_MsgIncreasePositionMargin.py +++ b/examples/chain_client/13_MsgIncreasePositionMargin.py @@ -66,7 +66,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/15_MsgWithdraw.py b/examples/chain_client/15_MsgWithdraw.py index a8c267d8..b198c0aa 100644 --- a/examples/chain_client/15_MsgWithdraw.py +++ b/examples/chain_client/15_MsgWithdraw.py @@ -57,7 +57,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/16_MsgSubaccountTransfer.py b/examples/chain_client/16_MsgSubaccountTransfer.py index d87eb0ed..b68717b2 100644 --- a/examples/chain_client/16_MsgSubaccountTransfer.py +++ b/examples/chain_client/16_MsgSubaccountTransfer.py @@ -64,7 +64,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/17_MsgBatchUpdateOrders.py b/examples/chain_client/17_MsgBatchUpdateOrders.py index 557ffe46..9efdc0a0 100644 --- a/examples/chain_client/17_MsgBatchUpdateOrders.py +++ b/examples/chain_client/17_MsgBatchUpdateOrders.py @@ -153,7 +153,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/18_MsgBid.py b/examples/chain_client/18_MsgBid.py index 8e5f8d5e..1efaa3e3 100644 --- a/examples/chain_client/18_MsgBid.py +++ b/examples/chain_client/18_MsgBid.py @@ -56,7 +56,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/19_MsgGrant.py b/examples/chain_client/19_MsgGrant.py index 32a82fe7..111a050c 100644 --- a/examples/chain_client/19_MsgGrant.py +++ b/examples/chain_client/19_MsgGrant.py @@ -76,7 +76,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/1_MsgSend.py b/examples/chain_client/1_MsgSend.py index 6389c8be..1d926898 100644 --- a/examples/chain_client/1_MsgSend.py +++ b/examples/chain_client/1_MsgSend.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/20_MsgExec.py b/examples/chain_client/20_MsgExec.py index d5ff2dc5..1203ff90 100644 --- a/examples/chain_client/20_MsgExec.py +++ b/examples/chain_client/20_MsgExec.py @@ -83,7 +83,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/21_MsgRevoke.py b/examples/chain_client/21_MsgRevoke.py index 82663004..91bb192d 100644 --- a/examples/chain_client/21_MsgRevoke.py +++ b/examples/chain_client/21_MsgRevoke.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/22_MsgSendToEth.py b/examples/chain_client/22_MsgSendToEth.py index 59bdc877..06e2d78c 100644 --- a/examples/chain_client/22_MsgSendToEth.py +++ b/examples/chain_client/22_MsgSendToEth.py @@ -70,7 +70,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/23_MsgRelayPriceFeedPrice.py b/examples/chain_client/23_MsgRelayPriceFeedPrice.py index cc7055c9..b59b34a3 100644 --- a/examples/chain_client/23_MsgRelayPriceFeedPrice.py +++ b/examples/chain_client/23_MsgRelayPriceFeedPrice.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/24_MsgRewardsOptOut.py b/examples/chain_client/24_MsgRewardsOptOut.py index 5fa2f429..8beaa1f4 100644 --- a/examples/chain_client/24_MsgRewardsOptOut.py +++ b/examples/chain_client/24_MsgRewardsOptOut.py @@ -56,7 +56,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/25_MsgDelegate.py b/examples/chain_client/25_MsgDelegate.py index ada14ce0..e32f6691 100644 --- a/examples/chain_client/25_MsgDelegate.py +++ b/examples/chain_client/25_MsgDelegate.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/26_MsgWithdrawDelegatorReward.py b/examples/chain_client/26_MsgWithdrawDelegatorReward.py deleted file mode 100644 index f9370c23..00000000 --- a/examples/chain_client/26_MsgWithdrawDelegatorReward.py +++ /dev/null @@ -1,81 +0,0 @@ -import asyncio -import os - -import dotenv -from grpc import RpcError - -from pyinjective.async_client import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE -from pyinjective.core.network import Network -from pyinjective.transaction import Transaction -from pyinjective.wallet import PrivateKey - - -async def main() -> None: - dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") - - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - composer = await client.composer() - await client.sync_timeout_height() - - # load account - priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - # prepare tx msg - validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" - - msg = composer.MsgWithdrawDelegatorReward( - delegator_address=address.to_acc_bech32(), validator_address=validator_address - ) - - # build sim tx - tx = ( - Transaction() - .with_messages(msg) - .with_sequence(client.get_sequence()) - .with_account_num(client.get_number()) - .with_chain_id(network.chain_id) - ) - sim_sign_doc = tx.get_sign_doc(pub_key) - sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) - sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key) - - # simulate tx - try: - sim_res = await client.simulate(sim_tx_raw_bytes) - except RpcError as ex: - print(ex) - return - - # build tx - gas_price = GAS_PRICE - gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation - gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") - fee = [ - composer.Coin( - amount=gas_price * gas_limit, - denom=network.fee_denom, - ) - ] - tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height) - sign_doc = tx.get_sign_doc(pub_key) - sig = priv_key.sign(sign_doc.SerializeToString()) - tx_raw_bytes = tx.get_tx_data(sig, pub_key) - - # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode - res = await client.broadcast_tx_sync_mode(tx_raw_bytes) - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/2_MsgDeposit.py b/examples/chain_client/2_MsgDeposit.py index 80587c55..80b9f652 100644 --- a/examples/chain_client/2_MsgDeposit.py +++ b/examples/chain_client/2_MsgDeposit.py @@ -57,7 +57,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/30_ExternalTransfer.py b/examples/chain_client/30_ExternalTransfer.py index 7ab6e0f2..3200be34 100644 --- a/examples/chain_client/30_ExternalTransfer.py +++ b/examples/chain_client/30_ExternalTransfer.py @@ -64,7 +64,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py index 57f5537b..2a58e173 100644 --- a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py +++ b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py @@ -81,7 +81,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py index 473e8e53..2d07658f 100644 --- a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py +++ b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py @@ -75,7 +75,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py index 15159f00..82107f3c 100644 --- a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py +++ b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py @@ -66,7 +66,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py index 55c308be..0f39dcdb 100644 --- a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py +++ b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py @@ -74,7 +74,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py index 7e865320..7b8a6567 100644 --- a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py +++ b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py @@ -76,7 +76,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/36_MsgRelayProviderPrices.py b/examples/chain_client/36_MsgRelayProviderPrices.py index 4ee5fc3f..1e3b9c8f 100644 --- a/examples/chain_client/36_MsgRelayProviderPrices.py +++ b/examples/chain_client/36_MsgRelayProviderPrices.py @@ -66,7 +66,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/3_MsgCreateSpotLimitOrder.py index dd06672a..d3ca5f16 100644 --- a/examples/chain_client/3_MsgCreateSpotLimitOrder.py +++ b/examples/chain_client/3_MsgCreateSpotLimitOrder.py @@ -77,7 +77,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/40_MsgExecuteContract.py b/examples/chain_client/40_MsgExecuteContract.py index f2d1b719..d18c6398 100644 --- a/examples/chain_client/40_MsgExecuteContract.py +++ b/examples/chain_client/40_MsgExecuteContract.py @@ -33,12 +33,12 @@ async def main() -> None: # prepare tx msg # NOTE: COIN MUST BE SORTED IN ALPHABETICAL ORDER BY DENOMS funds = [ - composer.Coin( + composer.coin( amount=69, denom="factory/inj1hdvy6tl89llqy3ze8lv6mz5qh66sx9enn0jxg6/inj12ngevx045zpvacus9s6anr258gkwpmthnz80e9", ), - composer.Coin(amount=420, denom="peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7"), - composer.Coin(amount=1, denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"), + composer.coin(amount=420, denom="peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7"), + composer.coin(amount=1, denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"), ] msg = composer.MsgExecuteContract( sender=address.to_acc_bech32(), @@ -71,7 +71,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/41_MsgCreateInsuranceFund.py b/examples/chain_client/41_MsgCreateInsuranceFund.py index 74f94bfa..99c10fc0 100644 --- a/examples/chain_client/41_MsgCreateInsuranceFund.py +++ b/examples/chain_client/41_MsgCreateInsuranceFund.py @@ -65,7 +65,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/42_MsgUnderwrite.py b/examples/chain_client/42_MsgUnderwrite.py index 20c65a64..16b75e70 100644 --- a/examples/chain_client/42_MsgUnderwrite.py +++ b/examples/chain_client/42_MsgUnderwrite.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/43_MsgRequestRedemption.py b/examples/chain_client/43_MsgRequestRedemption.py index 4413044b..ecc2793c 100644 --- a/examples/chain_client/43_MsgRequestRedemption.py +++ b/examples/chain_client/43_MsgRequestRedemption.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py b/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py deleted file mode 100644 index 2f67f6c4..00000000 --- a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py +++ /dev/null @@ -1,86 +0,0 @@ -import asyncio -import os - -import dotenv -from grpc import RpcError - -from pyinjective.async_client import AsyncClient -from pyinjective.composer import Composer as ProtoMsgComposer -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE -from pyinjective.core.network import Network -from pyinjective.transaction import Transaction -from pyinjective.wallet import PrivateKey - - -async def main() -> None: - dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") - - """For a validator to withdraw his rewards & commissions simultaneously""" - # select network: local, testnet, mainnet - network = Network.testnet() - composer = ProtoMsgComposer(network=network.string()) - - # initialize grpc client - client = AsyncClient(network, insecure=False) - await client.sync_timeout_height() - - # load account - # private key is that from the validator's wallet - priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - # prepare tx msg - validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" - - msg0 = composer.MsgWithdrawDelegatorReward( - delegator_address=address.to_acc_bech32(), validator_address=validator_address - ) - - msg1 = composer.MsgWithdrawValidatorCommission(validator_address=validator_address) - - # build sim tx - tx = ( - Transaction() - .with_messages(msg0, msg1) - .with_sequence(client.get_sequence()) - .with_account_num(client.get_number()) - .with_chain_id(network.chain_id) - ) - sim_sign_doc = tx.get_sign_doc(pub_key) - sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) - sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key) - - # simulate tx - try: - sim_res = await client.simulate(sim_tx_raw_bytes) - except RpcError as ex: - print(ex) - return - - # build tx - gas_price = GAS_PRICE - gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation - gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") - fee = [ - composer.Coin( - amount=gas_price * gas_limit, - denom=network.fee_denom, - ) - ] - tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height) - sign_doc = tx.get_sign_doc(pub_key) - sig = priv_key.sign(sign_doc.SerializeToString()) - tx_raw_bytes = tx.get_tx_data(sig, pub_key) - - # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode - res = await client.broadcast_tx_sync_mode(tx_raw_bytes) - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/4_MsgCreateSpotMarketOrder.py index 06a42a96..5229632f 100644 --- a/examples/chain_client/4_MsgCreateSpotMarketOrder.py +++ b/examples/chain_client/4_MsgCreateSpotMarketOrder.py @@ -75,7 +75,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/5_MsgCancelSpotOrder.py b/examples/chain_client/5_MsgCancelSpotOrder.py index 63167309..970b2190 100644 --- a/examples/chain_client/5_MsgCancelSpotOrder.py +++ b/examples/chain_client/5_MsgCancelSpotOrder.py @@ -63,7 +63,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py index e46f1acb..41a19307 100644 --- a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py @@ -77,7 +77,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/72_MsgMint.py b/examples/chain_client/72_MsgMint.py index d38449be..b6617431 100644 --- a/examples/chain_client/72_MsgMint.py +++ b/examples/chain_client/72_MsgMint.py @@ -26,7 +26,7 @@ async def main() -> None: pub_key = priv_key.to_public_key() address = pub_key.to_address() - amount = composer.Coin(amount=1_000_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") + amount = composer.coin(amount=1_000_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") message = composer.msg_mint( sender=address.to_acc_bech32(), diff --git a/examples/chain_client/73_MsgBurn.py b/examples/chain_client/73_MsgBurn.py index 441f4ee8..c4aa013a 100644 --- a/examples/chain_client/73_MsgBurn.py +++ b/examples/chain_client/73_MsgBurn.py @@ -26,7 +26,7 @@ async def main() -> None: pub_key = priv_key.to_public_key() address = pub_key.to_address() - amount = composer.Coin(amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") + amount = composer.coin(amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") message = composer.msg_burn( sender=address.to_acc_bech32(), diff --git a/examples/chain_client/76_MsgExecuteContractCompat.py b/examples/chain_client/76_MsgExecuteContractCompat.py index 892c125f..a195c7c4 100644 --- a/examples/chain_client/76_MsgExecuteContractCompat.py +++ b/examples/chain_client/76_MsgExecuteContractCompat.py @@ -68,7 +68,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/77_MsgLiquidatePosition.py b/examples/chain_client/77_MsgLiquidatePosition.py index 6dcbacfb..d80ba385 100644 --- a/examples/chain_client/77_MsgLiquidatePosition.py +++ b/examples/chain_client/77_MsgLiquidatePosition.py @@ -83,7 +83,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py index e7e06c62..37b305ed 100644 --- a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py +++ b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py @@ -76,7 +76,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/8_MsgCancelDerivativeOrder.py b/examples/chain_client/8_MsgCancelDerivativeOrder.py index 6a59167a..43180b1f 100644 --- a/examples/chain_client/8_MsgCancelDerivativeOrder.py +++ b/examples/chain_client/8_MsgCancelDerivativeOrder.py @@ -63,7 +63,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/distribution/10_SetWithdrawAddress.py b/examples/chain_client/distribution/10_SetWithdrawAddress.py new file mode 100644 index 00000000..b317a998 --- /dev/null +++ b/examples/chain_client/distribution/10_SetWithdrawAddress.py @@ -0,0 +1,46 @@ +import asyncio +import os + +import dotenv + +from pyinjective import AsyncClient, PrivateKey +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + withdraw_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + + message = composer.msg_set_withdraw_address( + delegator_address=address.to_acc_bech32(), + withdraw_address=withdraw_address, + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/11_WithdrawDelegatorReward.py b/examples/chain_client/distribution/11_WithdrawDelegatorReward.py new file mode 100644 index 00000000..02facdc7 --- /dev/null +++ b/examples/chain_client/distribution/11_WithdrawDelegatorReward.py @@ -0,0 +1,47 @@ +import asyncio +import os + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" + + message = composer.msg_withdraw_delegator_reward( + delegator_address=address.to_acc_bech32(), validator_address=validator_address + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/12_WithdrawValidatorCommission.py b/examples/chain_client/distribution/12_WithdrawValidatorCommission.py new file mode 100644 index 00000000..cd351d1f --- /dev/null +++ b/examples/chain_client/distribution/12_WithdrawValidatorCommission.py @@ -0,0 +1,45 @@ +import asyncio +import os + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" + + message = composer.msg_withdraw_validator_commission(validator_address=validator_address) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/13_FundCommunityPool.py b/examples/chain_client/distribution/13_FundCommunityPool.py new file mode 100644 index 00000000..c60475c8 --- /dev/null +++ b/examples/chain_client/distribution/13_FundCommunityPool.py @@ -0,0 +1,47 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective import AsyncClient, PrivateKey +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + amount = composer.create_coin_amount(amount=Decimal("0.1"), token_name="INJ") + + message = composer.msg_fund_community_pool( + amounts=[amount], + depositor=address.to_acc_bech32(), + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/pyinjective/composer.py b/pyinjective/composer.py index 720920d1..df353d6b 100644 --- a/pyinjective/composer.py +++ b/pyinjective/composer.py @@ -3,6 +3,7 @@ from decimal import Decimal from time import time from typing import Any, Dict, List, Optional +from warnings import warn from google.protobuf import any_pb2, json_format, timestamp_pb2 @@ -13,7 +14,10 @@ from pyinjective.proto.cosmos.authz.v1beta1 import authz_pb2 as cosmos_authz_pb, tx_pb2 as cosmos_authz_tx_pb from pyinjective.proto.cosmos.bank.v1beta1 import bank_pb2 as bank_pb, tx_pb2 as cosmos_bank_tx_pb from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as cosmos_dot_base_dot_v1beta1_dot_coin__pb2 -from pyinjective.proto.cosmos.distribution.v1beta1 import tx_pb2 as cosmos_distribution_tx_pb +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + distribution_pb2 as cosmos_distribution_pb2, + tx_pb2 as cosmos_distribution_tx_pb, +) from pyinjective.proto.cosmos.gov.v1beta1 import tx_pb2 as cosmos_gov_tx_pb from pyinjective.proto.cosmos.staking.v1beta1 import tx_pb2 as cosmos_staking_tx_pb from pyinjective.proto.cosmwasm.wasm.v1 import tx_pb2 as wasm_tx_pb @@ -129,8 +133,27 @@ def __init__( self.tokens = tokens def Coin(self, amount: int, denom: str): + """ + This method is deprecated and will be removed soon. Please use `coin` instead + """ + warn("This method is deprecated. Use coin instead", DeprecationWarning, stacklevel=2) return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=str(amount), denom=denom) + def coin(self, amount: int, denom: str): + """ + This method create an instance of Coin gRPC type, considering the amount is already expressed in chain format + """ + formatted_amount_string = str(int(amount)) + return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=formatted_amount_string, denom=denom) + + def create_coin_amount(self, amount: Decimal, token_name: str): + """ + This method create an instance of Coin gRPC type, considering the amount is already expressed in chain format + """ + token = self.tokens[token_name] + chain_amount = token.chain_formatted_value(human_readable_value=amount) + return self.coin(amount=int(chain_amount), denom=token.denom) + def get_order_mask(self, **kwargs): order_mask = 0 @@ -331,13 +354,12 @@ def BinaryOptionsOrder( ) def MsgSend(self, from_address: str, to_address: str, amount: float, denom: str): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return cosmos_bank_tx_pb.MsgSend( from_address=from_address, to_address=to_address, - amount=[self.Coin(amount=int(be_amount), denom=token.denom)], + amount=[coin], ) def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): @@ -350,13 +372,12 @@ def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): ) def MsgDeposit(self, sender: str, subaccount_id: str, amount: float, denom: str): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgDeposit( sender=sender, subaccount_id=subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=coin, ) def MsgCreateSpotLimitOrder( @@ -709,24 +730,22 @@ def MsgSubaccountTransfer( amount: int, denom: str, ): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgSubaccountTransfer( sender=sender, source_subaccount_id=source_subaccount_id, destination_subaccount_id=destination_subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=be_amount, ) def MsgWithdraw(self, sender: str, subaccount_id: str, amount: float, denom: str): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgWithdraw( sender=sender, subaccount_id=subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=be_amount, ) def MsgExternalTransfer( @@ -737,14 +756,13 @@ def MsgExternalTransfer( amount: int, denom: str, ): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgExternalTransfer( sender=sender, source_subaccount_id=source_subaccount_id, destination_subaccount_id=destination_subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=coin, ) def MsgBid(self, sender: str, bid_amount: float, round: float): @@ -753,7 +771,7 @@ def MsgBid(self, sender: str, bid_amount: float, round: float): return injective_auction_tx_pb.MsgBid( sender=sender, round=round, - bid_amount=self.Coin(amount=int(be_amount), denom=INJ_DENOM), + bid_amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), ) def MsgGrantGeneric(self, granter: str, grantee: str, msg_type: str, expire_in: int): @@ -851,15 +869,14 @@ def MsgRelayPriceFeedPrice(self, sender: list, base: list, quote: list, price: l return injective_oracle_tx_pb.MsgRelayPriceFeedPrice(sender=sender, base=base, quote=quote, price=price) def MsgSendToEth(self, denom: str, sender: str, eth_dest: str, amount: float, bridge_fee: float): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) - be_bridge_fee = token.chain_formatted_value(human_readable_value=Decimal(str(bridge_fee))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + be_bridge_fee = self.create_coin_amount(amount=Decimal(str(bridge_fee)), token_name=denom) return injective_peggy_tx_pb.MsgSendToEth( sender=sender, eth_dest=eth_dest, - amount=self.Coin(amount=int(be_amount), denom=token.denom), - bridge_fee=self.Coin(amount=int(be_bridge_fee), denom=token.denom), + amount=be_amount, + bridge_fee=be_bridge_fee, ) def MsgDelegate(self, delegator_address: str, validator_address: str, amount: float): @@ -868,7 +885,7 @@ def MsgDelegate(self, delegator_address: str, validator_address: str, amount: fl return cosmos_staking_tx_pb.MsgDelegate( delegator_address=delegator_address, validator_address=validator_address, - amount=self.Coin(amount=int(be_amount), denom=INJ_DENOM), + amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), ) def MsgCreateInsuranceFund( @@ -883,7 +900,7 @@ def MsgCreateInsuranceFund( initial_deposit: int, ): token = self.tokens[quote_denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(initial_deposit))) + deposit = self.create_coin_amount(Decimal(str(initial_deposit)), quote_denom) return injective_insurance_tx_pb.MsgCreateInsuranceFund( sender=sender, @@ -893,7 +910,7 @@ def MsgCreateInsuranceFund( oracle_quote=oracle_quote, oracle_type=oracle_type, expiry=expiry, - initial_deposit=self.Coin(amount=int(be_amount), denom=token.denom), + initial_deposit=deposit, ) def MsgUnderwrite( @@ -903,13 +920,12 @@ def MsgUnderwrite( quote_denom: str, amount: int, ): - token = self.tokens[quote_denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=quote_denom) return injective_insurance_tx_pb.MsgUnderwrite( sender=sender, market_id=market_id, - deposit=self.Coin(amount=int(be_amount), denom=token.denom), + deposit=be_amount, ) def MsgRequestRedemption( @@ -922,17 +938,9 @@ def MsgRequestRedemption( return injective_insurance_tx_pb.MsgRequestRedemption( sender=sender, market_id=market_id, - amount=self.Coin(amount=amount, denom=share_denom), + amount=self.coin(amount=amount, denom=share_denom), ) - def MsgWithdrawDelegatorReward(self, delegator_address: str, validator_address: str): - return cosmos_distribution_tx_pb.MsgWithdrawDelegatorReward( - delegator_address=delegator_address, validator_address=validator_address - ) - - def MsgWithdrawValidatorCommission(self, validator_address: str): - return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) - def MsgVote( self, proposal_id: str, @@ -1101,6 +1109,56 @@ def chain_stream_oracle_price_filter( symbols = symbols or ["*"] return chain_stream_query.OraclePriceFilter(symbol=symbols) + # ------------------------------------------------ + # Distribution module's messages + + def msg_set_withdraw_address(self, delegator_address: str, withdraw_address: str): + return cosmos_distribution_tx_pb.MsgSetWithdrawAddress( + delegator_address=delegator_address, withdraw_address=withdraw_address + ) + + # Deprecated + def MsgWithdrawDelegatorReward(self, delegator_address: str, validator_address: str): + """ + This method is deprecated and will be removed soon. Please use `msg_withdraw_delegator_reward` instead + """ + warn("This method is deprecated. Use msg_withdraw_delegator_reward instead", DeprecationWarning, stacklevel=2) + return cosmos_distribution_tx_pb.MsgWithdrawDelegatorReward( + delegator_address=delegator_address, validator_address=validator_address + ) + + def msg_withdraw_delegator_reward(self, delegator_address: str, validator_address: str): + return cosmos_distribution_tx_pb.MsgWithdrawDelegatorReward( + delegator_address=delegator_address, validator_address=validator_address + ) + + def MsgWithdrawValidatorCommission(self, validator_address: str): + """ + This method is deprecated and will be removed soon. Please use `msg_withdraw_validator_commission` instead + """ + warn( + "This method is deprecated. Use msg_withdraw_validator_commission instead", DeprecationWarning, stacklevel=2 + ) + return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) + + def msg_withdraw_validator_commission(self, validator_address: str): + return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) + + def msg_fund_community_pool(self, amounts: List[cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin], depositor: str): + return cosmos_distribution_tx_pb.MsgFundCommunityPool(amount=amounts, depositor=depositor) + + def msg_update_distribution_params(self, authority: str, community_tax: str, withdraw_address_enabled: bool): + params = cosmos_distribution_pb2.Params( + community_tax=community_tax, + withdraw_addr_enabled=withdraw_address_enabled, + ) + return cosmos_distribution_tx_pb.MsgUpdateParams(authority=authority, params=params) + + def msg_community_pool_spend( + self, authority: str, recipient: str, amount: List[cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin] + ): + return cosmos_distribution_tx_pb.MsgCommunityPoolSpend(authority=authority, recipient=recipient, amount=amount) + # data field format: [request-msg-header][raw-byte-msg-response] # you need to figure out this magic prefix number to trim request-msg-header off the data # this method handles only exchange responses diff --git a/pyinjective/core/broadcaster.py b/pyinjective/core/broadcaster.py index 22df562b..f279baea 100644 --- a/pyinjective/core/broadcaster.py +++ b/pyinjective/core/broadcaster.py @@ -264,7 +264,7 @@ async def configure_gas_fee_for_transaction( gas_limit = math.ceil(Decimal(str(sim_res["gasInfo"]["gasUsed"])) * self._gas_limit_adjustment_multiplier) fee = [ - self._composer.Coin( + self._composer.coin( amount=self._gas_price * gas_limit, denom=self._client.network.fee_denom, ) @@ -292,7 +292,7 @@ async def configure_gas_fee_for_transaction( transaction_gas_limit = messages_gas_limit + self.TRANSACTION_GAS_LIMIT fee = [ - self._composer.Coin( + self._composer.coin( amount=math.ceil(self._gas_price * transaction_gas_limit), denom=self._client.network.fee_denom, ) diff --git a/tests/test_composer.py b/tests/test_composer.py index 4f756c79..a0cca2ab 100644 --- a/tests/test_composer.py +++ b/tests/test_composer.py @@ -282,7 +282,7 @@ def test_msg_create_denom(self, basic_composer: Composer): def test_msg_mint(self, basic_composer: Composer): sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" - amount = basic_composer.Coin( + amount = basic_composer.coin( amount=1_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test", ) @@ -297,7 +297,7 @@ def test_msg_mint(self, basic_composer: Composer): def test_msg_burn(self, basic_composer: Composer): sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" - amount = basic_composer.Coin( + amount = basic_composer.coin( amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test", ) From d5666388af96f870b189ed030524814420bb5632 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 20 Feb 2024 12:52:10 -0300 Subject: [PATCH 18/44] (feat) Added support for all chain exchange module queries. Included new example scripts for all the queries and unit tests. --- ...drawAddress.py => 1_SetWithdrawAddress.py} | 0 ...Reward.py => 2_WithdrawDelegatorReward.py} | 0 ...on.py => 3_WithdrawValidatorCommission.py} | 0 ...ommunityPool.py => 4_FundCommunityPool.py} | 0 .../1_ValidatorDistributionInfo.py | 0 .../2_ValidatorOutstandingRewards.py | 0 .../{ => query}/3_ValidatorCommission.py | 0 .../{ => query}/4_ValidatorSlashes.py | 0 .../{ => query}/5_DelegationRewards.py | 0 .../{ => query}/6_DelegationTotalRewards.py | 0 .../{ => query}/7_DelegatorValidators.py | 0 .../{ => query}/8_DelegatorWithdrawAddress.py | 0 .../{ => query}/9_CommunityPool.py | 0 .../10_MsgSubaccountTransfer.py} | 0 .../11_MsgBatchUpdateOrders.py} | 0 .../12_MsgRewardsOptOut.py} | 0 .../15_ExternalTransfer.py} | 0 .../16_MsgCreateBinaryOptionsLimitOrder.py} | 0 .../17_MsgCreateBinaryOptionsMarketOrder.py} | 0 .../18_MsgCancelBinaryOptionsOrder.py} | 0 .../19_MsgLiquidatePosition.py} | 0 .../1_MsgDeposit.py} | 0 .../3_MsgCreateSpotLimitOrder.py | 0 .../4_MsgCreateSpotMarketOrder.py | 0 .../{ => exchange}/5_MsgCancelSpotOrder.py | 0 .../6_MsgCreateDerivativeLimitOrder.py | 0 .../7_MsgCreateDerivativeMarketOrder.py | 0 .../8_MsgCancelDerivativeOrder.py | 0 .../9_MsgWithdraw.py} | 0 .../exchange/query/10_SpotMarkets.py | 22 + .../exchange/query/11_SpotMarket.py | 21 + .../exchange/query/12_FullSpotMarkets.py | 23 + .../exchange/query/13_FullSpotMarket.py | 22 + .../exchange/query/14_SpotOrderbook.py | 26 + .../exchange/query/15_TraderSpotOrders.py | 37 + .../query/16_AccountAddressSpotOrders.py | 35 + .../exchange/query/17_SpotOrdersByHashes.py | 38 + .../exchange/query/18_SubaccountOrders.py | 37 + .../query/19_TraderSpotTransientOrders.py | 37 + .../exchange/query/1_SubaccountDeposits.py | 34 + .../exchange/query/20_SpotMidPriceAndTOB.py | 21 + .../query/21_DerivativeMidPriceAndTOB.py | 21 + .../exchange/query/22_DerivativeOrderbook.py | 25 + .../query/23_TraderDerivativeOrders.py | 37 + .../24_AccountAddressDerivativeOrders.py | 35 + .../query/25_DerivativeOrdersByHashes.py | 38 + .../26_TraderDerivativeTransientOrders.py | 37 + .../exchange/query/27_DerivativeMarkets.py | 22 + .../exchange/query/28_DerivativeMarket.py | 21 + .../query/29_DerivativeMarketAddress.py | 21 + .../exchange/query/2_SubaccountDeposit.py | 34 + .../exchange/query/30_SubaccountTradeNonce.py | 36 + .../exchange/query/31_Positions.py | 19 + .../exchange/query/32_SubaccountPositions.py | 36 + .../query/33_SubaccountPossitionInMarket.py | 37 + ...34_SubaccountEffectivePossitionInMarket.py | 37 + .../exchange/query/35_PerpetualMarketInfo.py | 21 + .../query/36_ExpiryFuturesMarketInfo.py | 21 + .../query/37_PerpetualMarketFunding.py | 21 + .../query/38_SubaccountOrderMetadata.py | 36 + .../exchange/query/39_TradeRewardPoints.py | 34 + .../exchange/query/3_ExchangeBalances.py | 18 + .../query/40_PendingTradeRewardPoints.py | 34 + .../query/41_FeeDiscountAccountInfo.py | 34 + .../exchange/query/42_FeeDiscountSchedule.py | 19 + .../exchange/query/43_BalanceMismatches.py | 19 + .../query/44_BalanceWithBalanceHolds.py | 19 + .../query/45_FeeDiscountTierStatistics.py | 19 + .../exchange/query/46_MitoVaultInfos.py | 19 + .../query/47_QueryMarketIDFromVault.py | 19 + .../query/48_HistoricalTradeRecords.py | 21 + .../exchange/query/49_IsOptedOutOfRewards.py | 34 + .../exchange/query/4_AggregateVolume.py | 36 + .../query/50_OptedOutOfRewardsAccounts.py | 19 + .../exchange/query/51_MarketVolatility.py | 30 + .../exchange/query/52_BinaryOptionsMarkets.py | 19 + .../53_TraderDerivativeConditionalOrders.py | 37 + .../54_MarketAtomicExecutionFeeMultiplier.py | 21 + .../exchange/query/5_AggregateVolumes.py | 34 + .../exchange/query/6_AggregateMarketVolume.py | 21 + .../query/7_AggregateMarketVolumes.py | 21 + .../exchange/query/8_DenomDecimal.py | 19 + .../exchange/query/9_DenomDecimals.py | 19 + pyinjective/async_client.py | 393 +++ .../chain/grpc/chain_grpc_exchange_api.py | 572 ++++ .../configurable_exchange_query_servicer.py | 325 +++ .../grpc/test_chain_grpc_exchange_api.py | 2466 +++++++++++++++++ 87 files changed, 5229 insertions(+) rename examples/chain_client/distribution/{10_SetWithdrawAddress.py => 1_SetWithdrawAddress.py} (100%) rename examples/chain_client/distribution/{11_WithdrawDelegatorReward.py => 2_WithdrawDelegatorReward.py} (100%) rename examples/chain_client/distribution/{12_WithdrawValidatorCommission.py => 3_WithdrawValidatorCommission.py} (100%) rename examples/chain_client/distribution/{13_FundCommunityPool.py => 4_FundCommunityPool.py} (100%) rename examples/chain_client/distribution/{ => query}/1_ValidatorDistributionInfo.py (100%) rename examples/chain_client/distribution/{ => query}/2_ValidatorOutstandingRewards.py (100%) rename examples/chain_client/distribution/{ => query}/3_ValidatorCommission.py (100%) rename examples/chain_client/distribution/{ => query}/4_ValidatorSlashes.py (100%) rename examples/chain_client/distribution/{ => query}/5_DelegationRewards.py (100%) rename examples/chain_client/distribution/{ => query}/6_DelegationTotalRewards.py (100%) rename examples/chain_client/distribution/{ => query}/7_DelegatorValidators.py (100%) rename examples/chain_client/distribution/{ => query}/8_DelegatorWithdrawAddress.py (100%) rename examples/chain_client/distribution/{ => query}/9_CommunityPool.py (100%) rename examples/chain_client/{16_MsgSubaccountTransfer.py => exchange/10_MsgSubaccountTransfer.py} (100%) rename examples/chain_client/{17_MsgBatchUpdateOrders.py => exchange/11_MsgBatchUpdateOrders.py} (100%) rename examples/chain_client/{24_MsgRewardsOptOut.py => exchange/12_MsgRewardsOptOut.py} (100%) rename examples/chain_client/{30_ExternalTransfer.py => exchange/15_ExternalTransfer.py} (100%) rename examples/chain_client/{31_MsgCreateBinaryOptionsLimitOrder.py => exchange/16_MsgCreateBinaryOptionsLimitOrder.py} (100%) rename examples/chain_client/{32_MsgCreateBinaryOptionsMarketOrder.py => exchange/17_MsgCreateBinaryOptionsMarketOrder.py} (100%) rename examples/chain_client/{33_MsgCancelBinaryOptionsOrder.py => exchange/18_MsgCancelBinaryOptionsOrder.py} (100%) rename examples/chain_client/{77_MsgLiquidatePosition.py => exchange/19_MsgLiquidatePosition.py} (100%) rename examples/chain_client/{2_MsgDeposit.py => exchange/1_MsgDeposit.py} (100%) rename examples/chain_client/{ => exchange}/3_MsgCreateSpotLimitOrder.py (100%) rename examples/chain_client/{ => exchange}/4_MsgCreateSpotMarketOrder.py (100%) rename examples/chain_client/{ => exchange}/5_MsgCancelSpotOrder.py (100%) rename examples/chain_client/{ => exchange}/6_MsgCreateDerivativeLimitOrder.py (100%) rename examples/chain_client/{ => exchange}/7_MsgCreateDerivativeMarketOrder.py (100%) rename examples/chain_client/{ => exchange}/8_MsgCancelDerivativeOrder.py (100%) rename examples/chain_client/{15_MsgWithdraw.py => exchange/9_MsgWithdraw.py} (100%) create mode 100644 examples/chain_client/exchange/query/10_SpotMarkets.py create mode 100644 examples/chain_client/exchange/query/11_SpotMarket.py create mode 100644 examples/chain_client/exchange/query/12_FullSpotMarkets.py create mode 100644 examples/chain_client/exchange/query/13_FullSpotMarket.py create mode 100644 examples/chain_client/exchange/query/14_SpotOrderbook.py create mode 100644 examples/chain_client/exchange/query/15_TraderSpotOrders.py create mode 100644 examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py create mode 100644 examples/chain_client/exchange/query/17_SpotOrdersByHashes.py create mode 100644 examples/chain_client/exchange/query/18_SubaccountOrders.py create mode 100644 examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py create mode 100644 examples/chain_client/exchange/query/1_SubaccountDeposits.py create mode 100644 examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py create mode 100644 examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py create mode 100644 examples/chain_client/exchange/query/22_DerivativeOrderbook.py create mode 100644 examples/chain_client/exchange/query/23_TraderDerivativeOrders.py create mode 100644 examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py create mode 100644 examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py create mode 100644 examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py create mode 100644 examples/chain_client/exchange/query/27_DerivativeMarkets.py create mode 100644 examples/chain_client/exchange/query/28_DerivativeMarket.py create mode 100644 examples/chain_client/exchange/query/29_DerivativeMarketAddress.py create mode 100644 examples/chain_client/exchange/query/2_SubaccountDeposit.py create mode 100644 examples/chain_client/exchange/query/30_SubaccountTradeNonce.py create mode 100644 examples/chain_client/exchange/query/31_Positions.py create mode 100644 examples/chain_client/exchange/query/32_SubaccountPositions.py create mode 100644 examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py create mode 100644 examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py create mode 100644 examples/chain_client/exchange/query/35_PerpetualMarketInfo.py create mode 100644 examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py create mode 100644 examples/chain_client/exchange/query/37_PerpetualMarketFunding.py create mode 100644 examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py create mode 100644 examples/chain_client/exchange/query/39_TradeRewardPoints.py create mode 100644 examples/chain_client/exchange/query/3_ExchangeBalances.py create mode 100644 examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py create mode 100644 examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py create mode 100644 examples/chain_client/exchange/query/42_FeeDiscountSchedule.py create mode 100644 examples/chain_client/exchange/query/43_BalanceMismatches.py create mode 100644 examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py create mode 100644 examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py create mode 100644 examples/chain_client/exchange/query/46_MitoVaultInfos.py create mode 100644 examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py create mode 100644 examples/chain_client/exchange/query/48_HistoricalTradeRecords.py create mode 100644 examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py create mode 100644 examples/chain_client/exchange/query/4_AggregateVolume.py create mode 100644 examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py create mode 100644 examples/chain_client/exchange/query/51_MarketVolatility.py create mode 100644 examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py create mode 100644 examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py create mode 100644 examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py create mode 100644 examples/chain_client/exchange/query/5_AggregateVolumes.py create mode 100644 examples/chain_client/exchange/query/6_AggregateMarketVolume.py create mode 100644 examples/chain_client/exchange/query/7_AggregateMarketVolumes.py create mode 100644 examples/chain_client/exchange/query/8_DenomDecimal.py create mode 100644 examples/chain_client/exchange/query/9_DenomDecimals.py create mode 100644 pyinjective/client/chain/grpc/chain_grpc_exchange_api.py create mode 100644 tests/client/chain/grpc/configurable_exchange_query_servicer.py create mode 100644 tests/client/chain/grpc/test_chain_grpc_exchange_api.py diff --git a/examples/chain_client/distribution/10_SetWithdrawAddress.py b/examples/chain_client/distribution/1_SetWithdrawAddress.py similarity index 100% rename from examples/chain_client/distribution/10_SetWithdrawAddress.py rename to examples/chain_client/distribution/1_SetWithdrawAddress.py diff --git a/examples/chain_client/distribution/11_WithdrawDelegatorReward.py b/examples/chain_client/distribution/2_WithdrawDelegatorReward.py similarity index 100% rename from examples/chain_client/distribution/11_WithdrawDelegatorReward.py rename to examples/chain_client/distribution/2_WithdrawDelegatorReward.py diff --git a/examples/chain_client/distribution/12_WithdrawValidatorCommission.py b/examples/chain_client/distribution/3_WithdrawValidatorCommission.py similarity index 100% rename from examples/chain_client/distribution/12_WithdrawValidatorCommission.py rename to examples/chain_client/distribution/3_WithdrawValidatorCommission.py diff --git a/examples/chain_client/distribution/13_FundCommunityPool.py b/examples/chain_client/distribution/4_FundCommunityPool.py similarity index 100% rename from examples/chain_client/distribution/13_FundCommunityPool.py rename to examples/chain_client/distribution/4_FundCommunityPool.py diff --git a/examples/chain_client/distribution/1_ValidatorDistributionInfo.py b/examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py similarity index 100% rename from examples/chain_client/distribution/1_ValidatorDistributionInfo.py rename to examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py diff --git a/examples/chain_client/distribution/2_ValidatorOutstandingRewards.py b/examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py similarity index 100% rename from examples/chain_client/distribution/2_ValidatorOutstandingRewards.py rename to examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py diff --git a/examples/chain_client/distribution/3_ValidatorCommission.py b/examples/chain_client/distribution/query/3_ValidatorCommission.py similarity index 100% rename from examples/chain_client/distribution/3_ValidatorCommission.py rename to examples/chain_client/distribution/query/3_ValidatorCommission.py diff --git a/examples/chain_client/distribution/4_ValidatorSlashes.py b/examples/chain_client/distribution/query/4_ValidatorSlashes.py similarity index 100% rename from examples/chain_client/distribution/4_ValidatorSlashes.py rename to examples/chain_client/distribution/query/4_ValidatorSlashes.py diff --git a/examples/chain_client/distribution/5_DelegationRewards.py b/examples/chain_client/distribution/query/5_DelegationRewards.py similarity index 100% rename from examples/chain_client/distribution/5_DelegationRewards.py rename to examples/chain_client/distribution/query/5_DelegationRewards.py diff --git a/examples/chain_client/distribution/6_DelegationTotalRewards.py b/examples/chain_client/distribution/query/6_DelegationTotalRewards.py similarity index 100% rename from examples/chain_client/distribution/6_DelegationTotalRewards.py rename to examples/chain_client/distribution/query/6_DelegationTotalRewards.py diff --git a/examples/chain_client/distribution/7_DelegatorValidators.py b/examples/chain_client/distribution/query/7_DelegatorValidators.py similarity index 100% rename from examples/chain_client/distribution/7_DelegatorValidators.py rename to examples/chain_client/distribution/query/7_DelegatorValidators.py diff --git a/examples/chain_client/distribution/8_DelegatorWithdrawAddress.py b/examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py similarity index 100% rename from examples/chain_client/distribution/8_DelegatorWithdrawAddress.py rename to examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py diff --git a/examples/chain_client/distribution/9_CommunityPool.py b/examples/chain_client/distribution/query/9_CommunityPool.py similarity index 100% rename from examples/chain_client/distribution/9_CommunityPool.py rename to examples/chain_client/distribution/query/9_CommunityPool.py diff --git a/examples/chain_client/16_MsgSubaccountTransfer.py b/examples/chain_client/exchange/10_MsgSubaccountTransfer.py similarity index 100% rename from examples/chain_client/16_MsgSubaccountTransfer.py rename to examples/chain_client/exchange/10_MsgSubaccountTransfer.py diff --git a/examples/chain_client/17_MsgBatchUpdateOrders.py b/examples/chain_client/exchange/11_MsgBatchUpdateOrders.py similarity index 100% rename from examples/chain_client/17_MsgBatchUpdateOrders.py rename to examples/chain_client/exchange/11_MsgBatchUpdateOrders.py diff --git a/examples/chain_client/24_MsgRewardsOptOut.py b/examples/chain_client/exchange/12_MsgRewardsOptOut.py similarity index 100% rename from examples/chain_client/24_MsgRewardsOptOut.py rename to examples/chain_client/exchange/12_MsgRewardsOptOut.py diff --git a/examples/chain_client/30_ExternalTransfer.py b/examples/chain_client/exchange/15_ExternalTransfer.py similarity index 100% rename from examples/chain_client/30_ExternalTransfer.py rename to examples/chain_client/exchange/15_ExternalTransfer.py diff --git a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py similarity index 100% rename from examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py rename to examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py diff --git a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py similarity index 100% rename from examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py rename to examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py diff --git a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py similarity index 100% rename from examples/chain_client/33_MsgCancelBinaryOptionsOrder.py rename to examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py diff --git a/examples/chain_client/77_MsgLiquidatePosition.py b/examples/chain_client/exchange/19_MsgLiquidatePosition.py similarity index 100% rename from examples/chain_client/77_MsgLiquidatePosition.py rename to examples/chain_client/exchange/19_MsgLiquidatePosition.py diff --git a/examples/chain_client/2_MsgDeposit.py b/examples/chain_client/exchange/1_MsgDeposit.py similarity index 100% rename from examples/chain_client/2_MsgDeposit.py rename to examples/chain_client/exchange/1_MsgDeposit.py diff --git a/examples/chain_client/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py similarity index 100% rename from examples/chain_client/3_MsgCreateSpotLimitOrder.py rename to examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py diff --git a/examples/chain_client/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py similarity index 100% rename from examples/chain_client/4_MsgCreateSpotMarketOrder.py rename to examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py diff --git a/examples/chain_client/5_MsgCancelSpotOrder.py b/examples/chain_client/exchange/5_MsgCancelSpotOrder.py similarity index 100% rename from examples/chain_client/5_MsgCancelSpotOrder.py rename to examples/chain_client/exchange/5_MsgCancelSpotOrder.py diff --git a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py similarity index 100% rename from examples/chain_client/6_MsgCreateDerivativeLimitOrder.py rename to examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py diff --git a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py similarity index 100% rename from examples/chain_client/7_MsgCreateDerivativeMarketOrder.py rename to examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py diff --git a/examples/chain_client/8_MsgCancelDerivativeOrder.py b/examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py similarity index 100% rename from examples/chain_client/8_MsgCancelDerivativeOrder.py rename to examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py diff --git a/examples/chain_client/15_MsgWithdraw.py b/examples/chain_client/exchange/9_MsgWithdraw.py similarity index 100% rename from examples/chain_client/15_MsgWithdraw.py rename to examples/chain_client/exchange/9_MsgWithdraw.py diff --git a/examples/chain_client/exchange/query/10_SpotMarkets.py b/examples/chain_client/exchange/query/10_SpotMarkets.py new file mode 100644 index 00000000..4cedc9d7 --- /dev/null +++ b/examples/chain_client/exchange/query/10_SpotMarkets.py @@ -0,0 +1,22 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_markets = await client.fetch_chain_spot_markets( + status="Active", + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(spot_markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/11_SpotMarket.py b/examples/chain_client/exchange/query/11_SpotMarket.py new file mode 100644 index 00000000..0e774edf --- /dev/null +++ b/examples/chain_client/exchange/query/11_SpotMarket.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_market = await client.fetch_chain_spot_market( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(spot_market) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/12_FullSpotMarkets.py b/examples/chain_client/exchange/query/12_FullSpotMarkets.py new file mode 100644 index 00000000..cfefee28 --- /dev/null +++ b/examples/chain_client/exchange/query/12_FullSpotMarkets.py @@ -0,0 +1,23 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_markets = await client.fetch_chain_full_spot_markets( + status="Active", + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + with_mid_price_and_tob=True, + ) + print(spot_markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/13_FullSpotMarket.py b/examples/chain_client/exchange/query/13_FullSpotMarket.py new file mode 100644 index 00000000..6a39269d --- /dev/null +++ b/examples/chain_client/exchange/query/13_FullSpotMarket.py @@ -0,0 +1,22 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_market = await client.fetch_chain_full_spot_market( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + with_mid_price_and_tob=True, + ) + print(spot_market) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/14_SpotOrderbook.py b/examples/chain_client/exchange/query/14_SpotOrderbook.py new file mode 100644 index 00000000..7b5a9aa1 --- /dev/null +++ b/examples/chain_client/exchange/query/14_SpotOrderbook.py @@ -0,0 +1,26 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + pagination = PaginationOption(limit=2) + + orderbook = await client.fetch_chain_spot_orderbook( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + order_side="Buy", + pagination=pagination, + ) + print(orderbook) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/15_TraderSpotOrders.py b/examples/chain_client/exchange/query/15_TraderSpotOrders.py new file mode 100644 index 00000000..0cc96b6f --- /dev/null +++ b/examples/chain_client/exchange/query/15_TraderSpotOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_trader_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py b/examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py new file mode 100644 index 00000000..8e50fa95 --- /dev/null +++ b/examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py @@ -0,0 +1,35 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + orders = await client.fetch_chain_account_address_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + account_address=address.to_acc_bech32(), + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/17_SpotOrdersByHashes.py b/examples/chain_client/exchange/query/17_SpotOrdersByHashes.py new file mode 100644 index 00000000..641eb6f5 --- /dev/null +++ b/examples/chain_client/exchange/query/17_SpotOrdersByHashes.py @@ -0,0 +1,38 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_spot_orders_by_hashes( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id=subaccount_id, + order_hashes=["0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"], + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/18_SubaccountOrders.py b/examples/chain_client/exchange/query/18_SubaccountOrders.py new file mode 100644 index 00000000..4983f827 --- /dev/null +++ b/examples/chain_client/exchange/query/18_SubaccountOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_subaccount_orders( + subaccount_id=subaccount_id, + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py b/examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py new file mode 100644 index 00000000..2b29c2c0 --- /dev/null +++ b/examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_trader_spot_transient_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/1_SubaccountDeposits.py b/examples/chain_client/exchange/query/1_SubaccountDeposits.py new file mode 100644 index 00000000..f9afb8ae --- /dev/null +++ b/examples/chain_client/exchange/query/1_SubaccountDeposits.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + deposits = await client.fetch_subaccount_deposits(subaccount_id=subaccount_id) + print(deposits) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py b/examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py new file mode 100644 index 00000000..35493ffd --- /dev/null +++ b/examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + prices = await client.fetch_spot_mid_price_and_tob( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(prices) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py b/examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py new file mode 100644 index 00000000..5b5c5fff --- /dev/null +++ b/examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + prices = await client.fetch_derivative_mid_price_and_tob( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(prices) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/22_DerivativeOrderbook.py b/examples/chain_client/exchange/query/22_DerivativeOrderbook.py new file mode 100644 index 00000000..465a62b6 --- /dev/null +++ b/examples/chain_client/exchange/query/22_DerivativeOrderbook.py @@ -0,0 +1,25 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + pagination = PaginationOption(limit=2) + + orderbook = await client.fetch_chain_derivative_orderbook( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + pagination=pagination, + ) + print(orderbook) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py b/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py new file mode 100644 index 00000000..61e98ba1 --- /dev/null +++ b/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_trader_spot_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py b/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py new file mode 100644 index 00000000..469c99fb --- /dev/null +++ b/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py @@ -0,0 +1,35 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + orders = await client.fetch_chain_account_address_spot_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + account_address=address.to_acc_bech32(), + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py b/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py new file mode 100644 index 00000000..ea700e6d --- /dev/null +++ b/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py @@ -0,0 +1,38 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_spot_orders_by_hashes( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id=subaccount_id, + order_hashes=["0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"], + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py b/examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py new file mode 100644 index 00000000..c5548d59 --- /dev/null +++ b/examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_trader_derivative_transient_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/27_DerivativeMarkets.py b/examples/chain_client/exchange/query/27_DerivativeMarkets.py new file mode 100644 index 00000000..2f4bbc5a --- /dev/null +++ b/examples/chain_client/exchange/query/27_DerivativeMarkets.py @@ -0,0 +1,22 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + derivative_markets = await client.fetch_chain_derivative_markets( + status="Active", + market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"], + ) + print(derivative_markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/28_DerivativeMarket.py b/examples/chain_client/exchange/query/28_DerivativeMarket.py new file mode 100644 index 00000000..152381f5 --- /dev/null +++ b/examples/chain_client/exchange/query/28_DerivativeMarket.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + derivative_market = await client.fetch_chain_derivative_market( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(derivative_market) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/29_DerivativeMarketAddress.py b/examples/chain_client/exchange/query/29_DerivativeMarketAddress.py new file mode 100644 index 00000000..c2d88805 --- /dev/null +++ b/examples/chain_client/exchange/query/29_DerivativeMarketAddress.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + address = await client.fetch_derivative_market_address( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(address) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/2_SubaccountDeposit.py b/examples/chain_client/exchange/query/2_SubaccountDeposit.py new file mode 100644 index 00000000..5002397d --- /dev/null +++ b/examples/chain_client/exchange/query/2_SubaccountDeposit.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + deposit = await client.fetch_subaccount_deposit(subaccount_id=subaccount_id, denom="inj") + print(deposit) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/30_SubaccountTradeNonce.py b/examples/chain_client/exchange/query/30_SubaccountTradeNonce.py new file mode 100644 index 00000000..ad81aca3 --- /dev/null +++ b/examples/chain_client/exchange/query/30_SubaccountTradeNonce.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + nonce = await client.fetch_subaccount_trade_nonce( + subaccount_id=subaccount_id, + ) + print(nonce) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/31_Positions.py b/examples/chain_client/exchange/query/31_Positions.py new file mode 100644 index 00000000..ae494b6a --- /dev/null +++ b/examples/chain_client/exchange/query/31_Positions.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + positions = await client.fetch_chain_positions() + print(positions) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/32_SubaccountPositions.py b/examples/chain_client/exchange/query/32_SubaccountPositions.py new file mode 100644 index 00000000..000d95b6 --- /dev/null +++ b/examples/chain_client/exchange/query/32_SubaccountPositions.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + positions = await client.fetch_chain_subaccount_positions( + subaccount_id=subaccount_id, + ) + print(positions) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py b/examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py new file mode 100644 index 00000000..4e0f1ddb --- /dev/null +++ b/examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + position = await client.fetch_chain_subaccount_position_in_market( + subaccount_id=subaccount_id, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(position) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py b/examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py new file mode 100644 index 00000000..e729e77c --- /dev/null +++ b/examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + position = await client.fetch_chain_subaccount_effective_position_in_market( + subaccount_id=subaccount_id, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(position) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/35_PerpetualMarketInfo.py b/examples/chain_client/exchange/query/35_PerpetualMarketInfo.py new file mode 100644 index 00000000..ca27f552 --- /dev/null +++ b/examples/chain_client/exchange/query/35_PerpetualMarketInfo.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_info = await client.fetch_chain_perpetual_market_info( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(market_info) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py b/examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py new file mode 100644 index 00000000..4053013c --- /dev/null +++ b/examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_info = await client.fetch_chain_expiry_futures_market_info( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(market_info) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/37_PerpetualMarketFunding.py b/examples/chain_client/exchange/query/37_PerpetualMarketFunding.py new file mode 100644 index 00000000..099c2a0f --- /dev/null +++ b/examples/chain_client/exchange/query/37_PerpetualMarketFunding.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + funding = await client.fetch_chain_perpetual_market_funding( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(funding) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py b/examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py new file mode 100644 index 00000000..f4af9d38 --- /dev/null +++ b/examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + metadata = await client.fetch_subaccount_order_metadata( + subaccount_id=subaccount_id, + ) + print(metadata) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/39_TradeRewardPoints.py b/examples/chain_client/exchange/query/39_TradeRewardPoints.py new file mode 100644 index 00000000..13f08730 --- /dev/null +++ b/examples/chain_client/exchange/query/39_TradeRewardPoints.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + points = await client.fetch_trade_reward_points( + accounts=[address.to_acc_bech32()], + ) + print(points) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/3_ExchangeBalances.py b/examples/chain_client/exchange/query/3_ExchangeBalances.py new file mode 100644 index 00000000..091bf10c --- /dev/null +++ b/examples/chain_client/exchange/query/3_ExchangeBalances.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + # initialize grpc client + client = AsyncClient(network) + + balances = await client.fetch_exchange_balances() + print(balances) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py b/examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py new file mode 100644 index 00000000..fa3e8aa2 --- /dev/null +++ b/examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + points = await client.fetch_pending_trade_reward_points( + accounts=[address.to_acc_bech32()], + ) + print(points) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py b/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py new file mode 100644 index 00000000..15fbb7ce --- /dev/null +++ b/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + fee_discount = await client.fetch_fee_discount_account_info( + account=address.to_acc_bech32(), + ) + print(fee_discount) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py b/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py new file mode 100644 index 00000000..a0ae96cb --- /dev/null +++ b/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + schedule = await client.fetch_fee_discount_schedule() + print(schedule) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/43_BalanceMismatches.py b/examples/chain_client/exchange/query/43_BalanceMismatches.py new file mode 100644 index 00000000..c7f7ca5e --- /dev/null +++ b/examples/chain_client/exchange/query/43_BalanceMismatches.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + mismatches = await client.fetch_balance_mismatches(dust_factor=1) + print(mismatches) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py b/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py new file mode 100644 index 00000000..6587c59a --- /dev/null +++ b/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + balance = await client.fetch_balance_with_balance_holds() + print(balance) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py b/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py new file mode 100644 index 00000000..5671e4ce --- /dev/null +++ b/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + statistics = await client.fetch_fee_discount_tier_statistics() + print(statistics) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/46_MitoVaultInfos.py b/examples/chain_client/exchange/query/46_MitoVaultInfos.py new file mode 100644 index 00000000..3faa5cb9 --- /dev/null +++ b/examples/chain_client/exchange/query/46_MitoVaultInfos.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + infos = await client.fetch_mito_vault_infos() + print(infos) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py b/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py new file mode 100644 index 00000000..e699dbaa --- /dev/null +++ b/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_id = await client.fetch_market_id_from_vault(vault_address="inj1qg5ega6dykkxc307y25pecuufrjkxkag6xhp6y") + print(market_id) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py b/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py new file mode 100644 index 00000000..6b93200f --- /dev/null +++ b/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + records = await client.fetch_historical_trade_records( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + ) + print(records) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py b/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py new file mode 100644 index 00000000..28c0925c --- /dev/null +++ b/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + is_opted_out = await client.fetch_is_opted_out_of_rewards( + account=address.to_acc_bech32(), + ) + print(is_opted_out) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/4_AggregateVolume.py b/examples/chain_client/exchange/query/4_AggregateVolume.py new file mode 100644 index 00000000..35c334a5 --- /dev/null +++ b/examples/chain_client/exchange/query/4_AggregateVolume.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + + subaccount_id = address.get_subaccount_id(index=0) + + volume = await client.fetch_aggregate_volume(account=address.to_acc_bech32()) + print(volume) + + volume = await client.fetch_aggregate_volume(account=subaccount_id) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py b/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py new file mode 100644 index 00000000..9940f799 --- /dev/null +++ b/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + opted_out = await client.fetch_opted_out_of_rewards_accounts() + print(opted_out) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/51_MarketVolatility.py b/examples/chain_client/exchange/query/51_MarketVolatility.py new file mode 100644 index 00000000..3173ca39 --- /dev/null +++ b/examples/chain_client/exchange/query/51_MarketVolatility.py @@ -0,0 +1,30 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + trade_grouping_sec = 10 + max_age = 0 + include_raw_history = True + include_metadata = True + volatility = await client.fetch_market_volatility( + market_id=market_id, + trade_grouping_sec=trade_grouping_sec, + max_age=max_age, + include_raw_history=include_raw_history, + include_metadata=include_metadata, + ) + print(volatility) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py b/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py new file mode 100644 index 00000000..4448a4ec --- /dev/null +++ b/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + markets = await client.fetch_chain_binary_options_markets(status="Active") + print(markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py b/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py new file mode 100644 index 00000000..fd65e68f --- /dev/null +++ b/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_trader_derivative_conditional_orders( + subaccount_id=subaccount_id, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py b/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py new file mode 100644 index 00000000..328028d3 --- /dev/null +++ b/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + multiplier = await client.fetch_market_atomic_execution_fee_multiplier( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(multiplier) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/5_AggregateVolumes.py b/examples/chain_client/exchange/query/5_AggregateVolumes.py new file mode 100644 index 00000000..6effe4be --- /dev/null +++ b/examples/chain_client/exchange/query/5_AggregateVolumes.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + + volume = await client.fetch_aggregate_volumes( + accounts=[address.to_acc_bech32()], + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/6_AggregateMarketVolume.py b/examples/chain_client/exchange/query/6_AggregateMarketVolume.py new file mode 100644 index 00000000..b3262d82 --- /dev/null +++ b/examples/chain_client/exchange/query/6_AggregateMarketVolume.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + + volume = await client.fetch_aggregate_market_volume(market_id=market_id) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/7_AggregateMarketVolumes.py b/examples/chain_client/exchange/query/7_AggregateMarketVolumes.py new file mode 100644 index 00000000..23dfa0ec --- /dev/null +++ b/examples/chain_client/exchange/query/7_AggregateMarketVolumes.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + volume = await client.fetch_aggregate_market_volumes( + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/8_DenomDecimal.py b/examples/chain_client/exchange/query/8_DenomDecimal.py new file mode 100644 index 00000000..2079f5e8 --- /dev/null +++ b/examples/chain_client/exchange/query/8_DenomDecimal.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + deposits = await client.fetch_denom_decimal(denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5") + print(deposits) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/9_DenomDecimals.py b/examples/chain_client/exchange/query/9_DenomDecimals.py new file mode 100644 index 00000000..d96df30b --- /dev/null +++ b/examples/chain_client/exchange/query/9_DenomDecimals.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + deposits = await client.fetch_denom_decimals(denoms=["inj", "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"]) + print(deposits) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index dea12f12..0af37da0 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -13,6 +13,7 @@ from pyinjective.client.chain.grpc.chain_grpc_authz_api import ChainGrpcAuthZApi from pyinjective.client.chain.grpc.chain_grpc_bank_api import ChainGrpcBankApi from pyinjective.client.chain.grpc.chain_grpc_distribution_api import ChainGrpcDistributionApi +from pyinjective.client.chain.grpc.chain_grpc_exchange_api import ChainGrpcExchangeApi from pyinjective.client.chain.grpc.chain_grpc_token_factory_api import ChainGrpcTokenFactoryApi from pyinjective.client.chain.grpc.chain_grpc_wasm_api import ChainGrpcWasmApi from pyinjective.client.chain.grpc_stream.chain_grpc_chain_stream import ChainGrpcChainStream @@ -185,6 +186,12 @@ def __init__( metadata_query_provider=self._chain_cookie_metadata_requestor ), ) + self.chain_exchange_api = ChainGrpcExchangeApi( + channel=self.chain_channel, + metadata_provider=lambda: self.network.chain_metadata( + metadata_query_provider=self._chain_cookie_metadata_requestor + ), + ) self.token_factory_api = ChainGrpcTokenFactoryApi( channel=self.chain_channel, metadata_provider=lambda: self.network.chain_metadata( @@ -639,6 +646,392 @@ async def fetch_delegator_withdraw_address( async def fetch_community_pool(self) -> Dict[str, Any]: return await self.distribution_api.fetch_community_pool() + # Exchange module + + async def fetch_subaccount_deposits( + self, + subaccount_id: Optional[str] = None, + subaccount_trader: Optional[str] = None, + subaccount_nonce: Optional[int] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_deposits( + subaccount_id=subaccount_id, + subaccount_trader=subaccount_trader, + subaccount_nonce=subaccount_nonce, + ) + + async def fetch_subaccount_deposit( + self, + subaccount_id: str, + denom: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_deposit( + subaccount_id=subaccount_id, + denom=denom, + ) + + async def fetch_exchange_balances(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_exchange_balances() + + async def fetch_aggregate_volume(self, account: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_volume(account=account) + + async def fetch_aggregate_volumes( + self, + accounts: Optional[List[str]] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_volumes( + accounts=accounts, + market_ids=market_ids, + ) + + async def fetch_aggregate_market_volume( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_market_volume( + market_id=market_id, + ) + + async def fetch_aggregate_market_volumes( + self, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_market_volumes( + market_ids=market_ids, + ) + + async def fetch_denom_decimal(self, denom: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_denom_decimal(denom=denom) + + async def fetch_denom_decimals(self, denoms: Optional[List[str]] = None) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_denom_decimals(denoms=denoms) + + async def fetch_chain_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_markets( + status=status, + market_ids=market_ids, + ) + + async def fetch_chain_spot_market( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_market( + market_id=market_id, + ) + + async def fetch_chain_full_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_full_spot_markets( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + + async def fetch_chain_full_spot_market( + self, + market_id: str, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_full_spot_market( + market_id=market_id, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + + async def fetch_chain_spot_orderbook( + self, + market_id: str, + order_side: Optional[str] = None, + limit_cumulative_notional: Optional[str] = None, + limit_cumulative_quantity: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + # Order side could be "Side_Unspecified", "Buy", "Sell" + return await self.chain_exchange_api.fetch_spot_orderbook( + market_id=market_id, + order_side=order_side, + limit_cumulative_notional=limit_cumulative_notional, + limit_cumulative_quantity=limit_cumulative_quantity, + pagination=pagination, + ) + + async def fetch_chain_trader_spot_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_spot_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_chain_account_address_spot_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_account_address_spot_orders( + market_id=market_id, + account_address=account_address, + ) + + async def fetch_chain_spot_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_orders_by_hashes( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + + async def fetch_chain_subaccount_orders( + self, + subaccount_id: str, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_orders( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_chain_trader_spot_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_spot_transient_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_spot_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_mid_price_and_tob( + market_id=market_id, + ) + + async def fetch_derivative_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_mid_price_and_tob( + market_id=market_id, + ) + + async def fetch_chain_derivative_orderbook( + self, + market_id: str, + limit_cumulative_notional: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_orderbook( + market_id=market_id, + limit_cumulative_notional=limit_cumulative_notional, + pagination=pagination, + ) + + async def fetch_chain_trader_derivative_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_derivative_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_chain_account_address_derivative_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_account_address_derivative_orders( + market_id=market_id, + account_address=account_address, + ) + + async def fetch_chain_derivative_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_orders_by_hashes( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + + async def fetch_chain_trader_derivative_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_derivative_transient_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_chain_derivative_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_markets( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + + async def fetch_chain_derivative_market( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_market( + market_id=market_id, + ) + + async def fetch_derivative_market_address(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_market_address(market_id=market_id) + + async def fetch_subaccount_trade_nonce(self, subaccount_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_trade_nonce(subaccount_id=subaccount_id) + + async def fetch_chain_positions(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_positions() + + async def fetch_chain_subaccount_positions(self, subaccount_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_positions(subaccount_id=subaccount_id) + + async def fetch_chain_subaccount_position_in_market(self, subaccount_id: str, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_chain_subaccount_effective_position_in_market( + self, subaccount_id: str, market_id: str + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_effective_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_chain_perpetual_market_info(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_perpetual_market_info(market_id=market_id) + + async def fetch_chain_expiry_futures_market_info(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_expiry_futures_market_info(market_id=market_id) + + async def fetch_chain_perpetual_market_funding(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_perpetual_market_funding(market_id=market_id) + + async def fetch_subaccount_order_metadata(self, subaccount_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_order_metadata(subaccount_id=subaccount_id) + + async def fetch_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trade_reward_points( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + + async def fetch_pending_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_pending_trade_reward_points( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + + async def fetch_fee_discount_account_info(self, account: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_fee_discount_account_info(account=account) + + async def fetch_fee_discount_schedule(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_fee_discount_schedule() + + async def fetch_balance_mismatches(self, dust_factor: int) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_balance_mismatches(dust_factor=dust_factor) + + async def fetch_balance_with_balance_holds(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_balance_with_balance_holds() + + async def fetch_fee_discount_tier_statistics(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_fee_discount_tier_statistics() + + async def fetch_mito_vault_infos(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_mito_vault_infos() + + async def fetch_market_id_from_vault(self, vault_address: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_market_id_from_vault(vault_address=vault_address) + + async def fetch_historical_trade_records(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_historical_trade_records(market_id=market_id) + + async def fetch_is_opted_out_of_rewards(self, account: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_is_opted_out_of_rewards(account=account) + + async def fetch_opted_out_of_rewards_accounts(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_opted_out_of_rewards_accounts() + + async def fetch_market_volatility( + self, + market_id: str, + trade_grouping_sec: Optional[int] = None, + max_age: Optional[int] = None, + include_raw_history: Optional[bool] = None, + include_metadata: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_market_volatility( + market_id=market_id, + trade_grouping_sec=trade_grouping_sec, + max_age=max_age, + include_raw_history=include_raw_history, + include_metadata=include_metadata, + ) + + async def fetch_chain_binary_options_markets(self, status: Optional[str] = None) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_binary_options_markets(status=status) + + async def fetch_trader_derivative_conditional_orders( + self, + subaccount_id: Optional[str] = None, + market_id: Optional[str] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_derivative_conditional_orders( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_market_atomic_execution_fee_multiplier( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_market_atomic_execution_fee_multiplier( + market_id=market_id, + ) + # Injective Exchange client methods # Auction RPC diff --git a/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py b/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py new file mode 100644 index 00000000..217c0d34 --- /dev/null +++ b/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py @@ -0,0 +1,572 @@ +from typing import Any, Callable, Dict, List, Optional + +from grpc.aio import Channel + +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.proto.injective.exchange.v1beta1 import ( + query_pb2 as exchange_query_pb, + query_pb2_grpc as exchange_query_grpc, +) +from pyinjective.utils.grpc_api_request_assistant import GrpcApiRequestAssistant + + +class ChainGrpcExchangeApi: + def __init__(self, channel: Channel, metadata_provider: Callable): + self._stub = exchange_query_grpc.QueryStub(channel) + self._assistant = GrpcApiRequestAssistant(metadata_provider=metadata_provider) + + async def fetch_exchange_params(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryExchangeParamsRequest() + response = await self._execute_call(call=self._stub.QueryExchangeParams, request=request) + + return response + + async def fetch_subaccount_deposits( + self, + subaccount_id: Optional[str] = None, + subaccount_trader: Optional[str] = None, + subaccount_nonce: Optional[int] = None, + ) -> Dict[str, Any]: + subaccount = None + if subaccount_trader is not None or subaccount_nonce is not None: + subaccount = exchange_query_pb.Subaccount( + trader=subaccount_trader, + subaccount_nonce=subaccount_nonce, + ) + + request = exchange_query_pb.QuerySubaccountDepositsRequest(subaccount_id=subaccount_id, subaccount=subaccount) + response = await self._execute_call(call=self._stub.SubaccountDeposits, request=request) + + return response + + async def fetch_subaccount_deposit( + self, + subaccount_id: str, + denom: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountDepositRequest( + subaccount_id=subaccount_id, + denom=denom, + ) + response = await self._execute_call(call=self._stub.SubaccountDeposit, request=request) + + return response + + async def fetch_exchange_balances(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryExchangeBalancesRequest() + response = await self._execute_call(call=self._stub.ExchangeBalances, request=request) + + return response + + async def fetch_aggregate_volume(self, account: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateVolumeRequest(account=account) + response = await self._execute_call(call=self._stub.AggregateVolume, request=request) + + return response + + async def fetch_aggregate_volumes( + self, + accounts: Optional[List[str]] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateVolumesRequest(accounts=accounts, market_ids=market_ids) + response = await self._execute_call(call=self._stub.AggregateVolumes, request=request) + + return response + + async def fetch_aggregate_market_volume(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateMarketVolumeRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.AggregateMarketVolume, request=request) + + return response + + async def fetch_aggregate_market_volumes(self, market_ids: Optional[List[str]] = None) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateMarketVolumesRequest(market_ids=market_ids) + response = await self._execute_call(call=self._stub.AggregateMarketVolumes, request=request) + + return response + + async def fetch_denom_decimal(self, denom: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryDenomDecimalRequest(denom=denom) + response = await self._execute_call(call=self._stub.DenomDecimal, request=request) + + return response + + async def fetch_denom_decimals(self, denoms: Optional[List[str]] = None) -> Dict[str, Any]: + request = exchange_query_pb.QueryDenomDecimalsRequest(denoms=denoms) + response = await self._execute_call(call=self._stub.DenomDecimals, request=request) + + return response + + async def fetch_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotMarketsRequest( + status=status, + market_ids=market_ids, + ) + response = await self._execute_call(call=self._stub.SpotMarkets, request=request) + + return response + + async def fetch_spot_market(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotMarketRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.SpotMarket, request=request) + + return response + + async def fetch_full_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFullSpotMarketsRequest( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + response = await self._execute_call(call=self._stub.FullSpotMarkets, request=request) + + return response + + async def fetch_full_spot_market( + self, + market_id: str, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFullSpotMarketRequest( + market_id=market_id, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + response = await self._execute_call(call=self._stub.FullSpotMarket, request=request) + + return response + + async def fetch_spot_orderbook( + self, + market_id: str, + order_side: Optional[str] = None, + limit_cumulative_notional: Optional[str] = None, + limit_cumulative_quantity: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + limit = None + if pagination is not None: + limit = pagination.limit + request = exchange_query_pb.QuerySpotOrderbookRequest( + market_id=market_id, + order_side=order_side, + limit=limit, + limit_cumulative_notional=limit_cumulative_notional, + limit_cumulative_quantity=limit_cumulative_quantity, + ) + response = await self._execute_call(call=self._stub.SpotOrderbook, request=request) + + return response + + async def fetch_trader_spot_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderSpotOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderSpotOrders, request=request) + + return response + + async def fetch_account_address_spot_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryAccountAddressSpotOrdersRequest( + market_id=market_id, + account_address=account_address, + ) + response = await self._execute_call(call=self._stub.AccountAddressSpotOrders, request=request) + + return response + + async def fetch_spot_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotOrdersByHashesRequest( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + response = await self._execute_call(call=self._stub.SpotOrdersByHashes, request=request) + + return response + + async def fetch_subaccount_orders( + self, + subaccount_id: str, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountOrdersRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SubaccountOrders, request=request) + + return response + + async def fetch_trader_spot_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderSpotOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderSpotTransientOrders, request=request) + + return response + + async def fetch_spot_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotMidPriceAndTOBRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SpotMidPriceAndTOB, request=request) + + return response + + async def fetch_derivative_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMidPriceAndTOBRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.DerivativeMidPriceAndTOB, request=request) + + return response + + async def fetch_derivative_orderbook( + self, + market_id: str, + limit_cumulative_notional: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + limit = None + if pagination is not None: + limit = pagination.limit + request = exchange_query_pb.QueryDerivativeOrderbookRequest( + market_id=market_id, + limit=limit, + limit_cumulative_notional=limit_cumulative_notional, + ) + response = await self._execute_call(call=self._stub.DerivativeOrderbook, request=request) + + return response + + async def fetch_trader_derivative_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderDerivativeOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderDerivativeOrders, request=request) + + return response + + async def fetch_account_address_derivative_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryAccountAddressDerivativeOrdersRequest( + market_id=market_id, + account_address=account_address, + ) + response = await self._execute_call(call=self._stub.AccountAddressDerivativeOrders, request=request) + + return response + + async def fetch_derivative_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeOrdersByHashesRequest( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + response = await self._execute_call(call=self._stub.DerivativeOrdersByHashes, request=request) + + return response + + async def fetch_trader_derivative_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderDerivativeOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderDerivativeTransientOrders, request=request) + + return response + + async def fetch_derivative_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMarketsRequest( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + response = await self._execute_call(call=self._stub.DerivativeMarkets, request=request) + + return response + + async def fetch_derivative_market( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMarketRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.DerivativeMarket, request=request) + + return response + + async def fetch_derivative_market_address( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMarketAddressRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.DerivativeMarketAddress, request=request) + + return response + + async def fetch_subaccount_trade_nonce(self, subaccount_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountTradeNonceRequest(subaccount_id=subaccount_id) + response = await self._execute_call(call=self._stub.SubaccountTradeNonce, request=request) + + return response + + async def fetch_positions(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryPositionsRequest() + response = await self._execute_call(call=self._stub.Positions, request=request) + + return response + + async def fetch_subaccount_positions(self, subaccount_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountPositionsRequest(subaccount_id=subaccount_id) + response = await self._execute_call(call=self._stub.SubaccountPositions, request=request) + + return response + + async def fetch_subaccount_position_in_market(self, subaccount_id: str, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountPositionInMarketRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SubaccountPositionInMarket, request=request) + + return response + + async def fetch_subaccount_effective_position_in_market(self, subaccount_id: str, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountEffectivePositionInMarketRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SubaccountEffectivePositionInMarket, request=request) + + return response + + async def fetch_perpetual_market_info(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryPerpetualMarketInfoRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.PerpetualMarketInfo, request=request) + + return response + + async def fetch_expiry_futures_market_info(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryExpiryFuturesMarketInfoRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.ExpiryFuturesMarketInfo, request=request) + + return response + + async def fetch_perpetual_market_funding(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryPerpetualMarketFundingRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.PerpetualMarketFunding, request=request) + + return response + + async def fetch_subaccount_order_metadata(self, subaccount_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountOrderMetadataRequest(subaccount_id=subaccount_id) + response = await self._execute_call(call=self._stub.SubaccountOrderMetadata, request=request) + + return response + + async def fetch_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTradeRewardPointsRequest( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + response = await self._execute_call(call=self._stub.TradeRewardPoints, request=request) + + return response + + async def fetch_pending_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTradeRewardPointsRequest( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + response = await self._execute_call(call=self._stub.PendingTradeRewardPoints, request=request) + + return response + + async def fetch_fee_discount_account_info( + self, + account: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFeeDiscountAccountInfoRequest(account=account) + response = await self._execute_call(call=self._stub.FeeDiscountAccountInfo, request=request) + + return response + + async def fetch_fee_discount_schedule(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryFeeDiscountScheduleRequest() + response = await self._execute_call(call=self._stub.FeeDiscountSchedule, request=request) + + return response + + async def fetch_balance_mismatches(self, dust_factor: int) -> Dict[str, Any]: + request = exchange_query_pb.QueryBalanceMismatchesRequest(dust_factor=dust_factor) + response = await self._execute_call(call=self._stub.BalanceMismatches, request=request) + + return response + + async def fetch_balance_with_balance_holds(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryBalanceWithBalanceHoldsRequest() + response = await self._execute_call(call=self._stub.BalanceWithBalanceHolds, request=request) + + return response + + async def fetch_fee_discount_tier_statistics(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryFeeDiscountTierStatisticsRequest() + response = await self._execute_call(call=self._stub.FeeDiscountTierStatistics, request=request) + + return response + + async def fetch_mito_vault_infos(self) -> Dict[str, Any]: + request = exchange_query_pb.MitoVaultInfosRequest() + response = await self._execute_call(call=self._stub.MitoVaultInfos, request=request) + + return response + + async def fetch_market_id_from_vault(self, vault_address: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryMarketIDFromVaultRequest(vault_address=vault_address) + response = await self._execute_call(call=self._stub.QueryMarketIDFromVault, request=request) + + return response + + async def fetch_historical_trade_records(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryHistoricalTradeRecordsRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.HistoricalTradeRecords, request=request) + + return response + + async def fetch_is_opted_out_of_rewards(self, account: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryIsOptedOutOfRewardsRequest(account=account) + response = await self._execute_call(call=self._stub.IsOptedOutOfRewards, request=request) + + return response + + async def fetch_opted_out_of_rewards_accounts(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryOptedOutOfRewardsAccountsRequest() + response = await self._execute_call(call=self._stub.OptedOutOfRewardsAccounts, request=request) + + return response + + async def fetch_market_volatility( + self, + market_id: str, + trade_grouping_sec: Optional[int] = None, + max_age: Optional[int] = None, + include_raw_history: Optional[bool] = None, + include_metadata: Optional[bool] = None, + ) -> Dict[str, Any]: + trade_history_options = exchange_query_pb.TradeHistoryOptions() + if trade_grouping_sec is not None: + trade_history_options.trade_grouping_sec = trade_grouping_sec + if max_age is not None: + trade_history_options.max_age = max_age + if include_raw_history is not None: + trade_history_options.include_raw_history = include_raw_history + if include_metadata is not None: + trade_history_options.include_metadata = include_metadata + request = exchange_query_pb.QueryMarketVolatilityRequest( + market_id=market_id, trade_history_options=trade_history_options + ) + response = await self._execute_call(call=self._stub.MarketVolatility, request=request) + + return response + + async def fetch_binary_options_markets(self, status: Optional[str] = None) -> Dict[str, Any]: + request = exchange_query_pb.QueryBinaryMarketsRequest(status=status) + response = await self._execute_call(call=self._stub.BinaryOptionsMarkets, request=request) + + return response + + async def fetch_trader_derivative_conditional_orders( + self, + subaccount_id: Optional[str] = None, + market_id: Optional[str] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderDerivativeConditionalOrdersRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.TraderDerivativeConditionalOrders, request=request) + + return response + + async def fetch_market_atomic_execution_fee_multiplier( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryMarketAtomicExecutionFeeMultiplierRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.MarketAtomicExecutionFeeMultiplier, request=request) + + return response + + async def _execute_call(self, call: Callable, request) -> Dict[str, Any]: + return await self._assistant.execute_call(call=call, request=request) diff --git a/tests/client/chain/grpc/configurable_exchange_query_servicer.py b/tests/client/chain/grpc/configurable_exchange_query_servicer.py new file mode 100644 index 00000000..267b08ce --- /dev/null +++ b/tests/client/chain/grpc/configurable_exchange_query_servicer.py @@ -0,0 +1,325 @@ +from collections import deque + +from pyinjective.proto.injective.exchange.v1beta1 import ( + query_pb2 as exchange_query_pb, + query_pb2_grpc as exchange_query_grpc, +) + + +class ConfigurableExchangeQueryServicer(exchange_query_grpc.QueryServicer): + def __init__(self): + super().__init__() + self.exchange_params = deque() + self.subaccount_deposits_responses = deque() + self.subaccount_deposit_responses = deque() + self.exchange_balances_responses = deque() + self.aggregate_volume_responses = deque() + self.aggregate_volumes_responses = deque() + self.aggregate_market_volume_responses = deque() + self.aggregate_market_volumes_responses = deque() + self.denom_decimal_responses = deque() + self.denom_decimals_responses = deque() + self.spot_markets_responses = deque() + self.spot_market_responses = deque() + self.full_spot_markets_responses = deque() + self.full_spot_market_responses = deque() + self.spot_orderbook_responses = deque() + self.trader_spot_orders_responses = deque() + self.account_address_spot_orders_responses = deque() + self.spot_orders_by_hashes_responses = deque() + self.subaccount_orders_responses = deque() + self.trader_spot_transient_orders_responses = deque() + self.spot_mid_price_and_tob_responses = deque() + self.derivative_mid_price_and_tob_responses = deque() + self.derivative_orderbook_responses = deque() + self.trader_derivative_orders_responses = deque() + self.account_address_derivative_orders_responses = deque() + self.derivative_orders_by_hashes_responses = deque() + self.trader_derivative_transient_orders_responses = deque() + self.derivative_markets_responses = deque() + self.derivative_market_responses = deque() + self.derivative_market_address_responses = deque() + self.subaccount_trade_nonce_responses = deque() + self.positions_responses = deque() + self.subaccount_positions_responses = deque() + self.subaccount_position_in_market_responses = deque() + self.subaccount_effective_position_in_market_responses = deque() + self.perpetual_market_info_responses = deque() + self.expiry_futures_market_info_responses = deque() + self.perpetual_market_funding_responses = deque() + self.subaccount_order_metadata_responses = deque() + self.trade_reward_points_responses = deque() + self.pending_trade_reward_points_responses = deque() + self.fee_discount_account_info_responses = deque() + self.fee_discount_schedule_responses = deque() + self.balance_mismatches_responses = deque() + self.balance_with_balance_holds_responses = deque() + self.fee_discount_tier_statistics_responses = deque() + self.mito_vault_infos_responses = deque() + self.market_id_from_vault_responses = deque() + self.historical_trade_records_responses = deque() + self.is_opted_out_of_rewards_responses = deque() + self.opted_out_of_rewards_accounts_responses = deque() + self.market_volatility_responses = deque() + self.binary_options_markets_responses = deque() + self.trader_derivative_conditional_orders_responses = deque() + self.market_atomic_execution_fee_multiplier_responses = deque() + + async def QueryExchangeParams( + self, request: exchange_query_pb.QueryExchangeParamsRequest, context=None, metadata=None + ): + return self.exchange_params.pop() + + async def SubaccountDeposits( + self, request: exchange_query_pb.QuerySubaccountDepositsRequest, context=None, metadata=None + ): + return self.subaccount_deposits_responses.pop() + + async def SubaccountDeposit( + self, request: exchange_query_pb.QuerySubaccountDepositRequest, context=None, metadata=None + ): + return self.subaccount_deposit_responses.pop() + + async def ExchangeBalances( + self, request: exchange_query_pb.QueryExchangeBalancesRequest, context=None, metadata=None + ): + return self.exchange_balances_responses.pop() + + async def AggregateVolume( + self, request: exchange_query_pb.QueryAggregateVolumeRequest, context=None, metadata=None + ): + return self.aggregate_volume_responses.pop() + + async def AggregateVolumes( + self, request: exchange_query_pb.QueryAggregateVolumesRequest, context=None, metadata=None + ): + return self.aggregate_volumes_responses.pop() + + async def AggregateMarketVolume( + self, request: exchange_query_pb.QueryAggregateMarketVolumeRequest, context=None, metadata=None + ): + return self.aggregate_market_volume_responses.pop() + + async def AggregateMarketVolumes( + self, request: exchange_query_pb.QueryAggregateMarketVolumesRequest, context=None, metadata=None + ): + return self.aggregate_market_volumes_responses.pop() + + async def DenomDecimal(self, request: exchange_query_pb.QueryDenomDecimalRequest, context=None, metadata=None): + return self.denom_decimal_responses.pop() + + async def DenomDecimals(self, request: exchange_query_pb.QueryDenomDecimalsRequest, context=None, metadata=None): + return self.denom_decimals_responses.pop() + + async def SpotMarkets(self, request: exchange_query_pb.QuerySpotMarketsRequest, context=None, metadata=None): + return self.spot_markets_responses.pop() + + async def SpotMarket(self, request: exchange_query_pb.QuerySpotMarketRequest, context=None, metadata=None): + return self.spot_market_responses.pop() + + async def FullSpotMarkets( + self, request: exchange_query_pb.QueryFullSpotMarketsRequest, context=None, metadata=None + ): + return self.full_spot_markets_responses.pop() + + async def FullSpotMarket(self, request: exchange_query_pb.QueryFullSpotMarketRequest, context=None, metadata=None): + return self.full_spot_market_responses.pop() + + async def SpotOrderbook(self, request: exchange_query_pb.QuerySpotOrderbookRequest, context=None, metadata=None): + return self.spot_orderbook_responses.pop() + + async def TraderSpotOrders( + self, request: exchange_query_pb.QueryTraderSpotOrdersRequest, context=None, metadata=None + ): + return self.trader_spot_orders_responses.pop() + + async def AccountAddressSpotOrders( + self, request: exchange_query_pb.QueryAccountAddressSpotOrdersRequest, context=None, metadata=None + ): + return self.account_address_spot_orders_responses.pop() + + async def SpotOrdersByHashes( + self, request: exchange_query_pb.QuerySpotOrdersByHashesRequest, context=None, metadata=None + ): + return self.spot_orders_by_hashes_responses.pop() + + async def SubaccountOrders( + self, request: exchange_query_pb.QuerySubaccountOrdersRequest, context=None, metadata=None + ): + return self.subaccount_orders_responses.pop() + + async def TraderSpotTransientOrders( + self, request: exchange_query_pb.QueryTraderSpotOrdersRequest, context=None, metadata=None + ): + return self.trader_spot_transient_orders_responses.pop() + + async def SpotMidPriceAndTOB( + self, request: exchange_query_pb.QuerySpotMidPriceAndTOBRequest, context=None, metadata=None + ): + return self.spot_mid_price_and_tob_responses.pop() + + async def DerivativeMidPriceAndTOB( + self, request: exchange_query_pb.QueryDerivativeMidPriceAndTOBRequest, context=None, metadata=None + ): + return self.derivative_mid_price_and_tob_responses.pop() + + async def DerivativeOrderbook( + self, request: exchange_query_pb.QueryDerivativeOrderbookRequest, context=None, metadata=None + ): + return self.derivative_orderbook_responses.pop() + + async def TraderDerivativeOrders( + self, request: exchange_query_pb.QueryTraderDerivativeOrdersRequest, context=None, metadata=None + ): + return self.trader_derivative_orders_responses.pop() + + async def AccountAddressDerivativeOrders( + self, request: exchange_query_pb.QueryAccountAddressDerivativeOrdersRequest, context=None, metadata=None + ): + return self.account_address_derivative_orders_responses.pop() + + async def DerivativeOrdersByHashes( + self, request: exchange_query_pb.QueryDerivativeOrdersByHashesRequest, context=None, metadata=None + ): + return self.derivative_orders_by_hashes_responses.pop() + + async def TraderDerivativeTransientOrders( + self, request: exchange_query_pb.QueryTraderDerivativeOrdersRequest, context=None, metadata=None + ): + return self.trader_derivative_transient_orders_responses.pop() + + async def DerivativeMarkets( + self, request: exchange_query_pb.QueryDerivativeMarketsRequest, context=None, metadata=None + ): + return self.derivative_markets_responses.pop() + + async def DerivativeMarket( + self, request: exchange_query_pb.QueryDerivativeMarketRequest, context=None, metadata=None + ): + return self.derivative_market_responses.pop() + + async def DerivativeMarketAddress( + self, request: exchange_query_pb.QueryDerivativeMarketAddressRequest, context=None, metadata=None + ): + return self.derivative_market_address_responses.pop() + + async def SubaccountTradeNonce( + self, request: exchange_query_pb.QuerySubaccountTradeNonceRequest, context=None, metadata=None + ): + return self.subaccount_trade_nonce_responses.pop() + + async def Positions(self, request: exchange_query_pb.QueryPositionsRequest, context=None, metadata=None): + return self.positions_responses.pop() + + async def SubaccountPositions( + self, request: exchange_query_pb.QuerySubaccountPositionsRequest, context=None, metadata=None + ): + return self.subaccount_positions_responses.pop() + + async def SubaccountPositionInMarket( + self, request: exchange_query_pb.QuerySubaccountPositionInMarketRequest, context=None, metadata=None + ): + return self.subaccount_position_in_market_responses.pop() + + async def SubaccountEffectivePositionInMarket( + self, request: exchange_query_pb.QuerySubaccountEffectivePositionInMarketRequest, context=None, metadata=None + ): + return self.subaccount_effective_position_in_market_responses.pop() + + async def PerpetualMarketInfo( + self, request: exchange_query_pb.QueryPerpetualMarketInfoRequest, context=None, metadata=None + ): + return self.perpetual_market_info_responses.pop() + + async def ExpiryFuturesMarketInfo( + self, request: exchange_query_pb.QueryExpiryFuturesMarketInfoRequest, context=None, metadata=None + ): + return self.expiry_futures_market_info_responses.pop() + + async def PerpetualMarketFunding( + self, request: exchange_query_pb.QueryPerpetualMarketFundingRequest, context=None, metadata=None + ): + return self.perpetual_market_funding_responses.pop() + + async def SubaccountOrderMetadata( + self, request: exchange_query_pb.QuerySubaccountOrderMetadataRequest, context=None, metadata=None + ): + return self.subaccount_order_metadata_responses.pop() + + async def TradeRewardPoints( + self, request: exchange_query_pb.QueryTradeRewardPointsRequest, context=None, metadata=None + ): + return self.trade_reward_points_responses.pop() + + async def PendingTradeRewardPoints( + self, request: exchange_query_pb.QueryTradeRewardPointsRequest, context=None, metadata=None + ): + return self.pending_trade_reward_points_responses.pop() + + async def FeeDiscountAccountInfo( + self, request: exchange_query_pb.QueryFeeDiscountAccountInfoRequest, context=None, metadata=None + ): + return self.fee_discount_account_info_responses.pop() + + async def FeeDiscountSchedule( + self, request: exchange_query_pb.QueryFeeDiscountScheduleRequest, context=None, metadata=None + ): + return self.fee_discount_schedule_responses.pop() + + async def BalanceMismatches( + self, request: exchange_query_pb.QueryBalanceMismatchesRequest, context=None, metadata=None + ): + return self.balance_mismatches_responses.pop() + + async def BalanceWithBalanceHolds( + self, request: exchange_query_pb.QueryBalanceWithBalanceHoldsRequest, context=None, metadata=None + ): + return self.balance_with_balance_holds_responses.pop() + + async def FeeDiscountTierStatistics( + self, request: exchange_query_pb.QueryFeeDiscountTierStatisticsRequest, context=None, metadata=None + ): + return self.fee_discount_tier_statistics_responses.pop() + + async def MitoVaultInfos(self, request: exchange_query_pb.MitoVaultInfosRequest, context=None, metadata=None): + return self.mito_vault_infos_responses.pop() + + async def QueryMarketIDFromVault( + self, request: exchange_query_pb.QueryMarketIDFromVaultRequest, context=None, metadata=None + ): + return self.market_id_from_vault_responses.pop() + + async def HistoricalTradeRecords( + self, request: exchange_query_pb.QueryHistoricalTradeRecordsRequest, context=None, metadata=None + ): + return self.historical_trade_records_responses.pop() + + async def IsOptedOutOfRewards( + self, request: exchange_query_pb.QueryIsOptedOutOfRewardsRequest, context=None, metadata=None + ): + return self.is_opted_out_of_rewards_responses.pop() + + async def OptedOutOfRewardsAccounts( + self, request: exchange_query_pb.QueryOptedOutOfRewardsAccountsRequest, context=None, metadata=None + ): + return self.opted_out_of_rewards_accounts_responses.pop() + + async def MarketVolatility( + self, request: exchange_query_pb.QueryMarketVolatilityRequest, context=None, metadata=None + ): + return self.market_volatility_responses.pop() + + async def BinaryOptionsMarkets( + self, request: exchange_query_pb.QueryBinaryMarketsRequest, context=None, metadata=None + ): + return self.binary_options_markets_responses.pop() + + async def TraderDerivativeConditionalOrders( + self, request: exchange_query_pb.QueryTraderDerivativeConditionalOrdersRequest, context=None, metadata=None + ): + return self.trader_derivative_conditional_orders_responses.pop() + + async def MarketAtomicExecutionFeeMultiplier( + self, request: exchange_query_pb.QueryMarketAtomicExecutionFeeMultiplierRequest, context=None, metadata=None + ): + return self.market_atomic_execution_fee_multiplier_responses.pop() diff --git a/tests/client/chain/grpc/test_chain_grpc_exchange_api.py b/tests/client/chain/grpc/test_chain_grpc_exchange_api.py new file mode 100644 index 00000000..54393a94 --- /dev/null +++ b/tests/client/chain/grpc/test_chain_grpc_exchange_api.py @@ -0,0 +1,2466 @@ +import base64 + +import grpc +import pytest + +from pyinjective.client.chain.grpc.chain_grpc_exchange_api import ChainGrpcExchangeApi +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network +from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as coin_pb +from pyinjective.proto.injective.exchange.v1beta1 import ( + exchange_pb2 as exchange_pb, + genesis_pb2 as genesis_pb, + query_pb2 as exchange_query_pb, +) +from pyinjective.proto.injective.oracle.v1beta1 import oracle_pb2 as oracle_pb +from tests.client.chain.grpc.configurable_exchange_query_servicer import ConfigurableExchangeQueryServicer + + +@pytest.fixture +def exchange_servicer(): + return ConfigurableExchangeQueryServicer() + + +class TestChainGrpcBankApi: + @pytest.mark.asyncio + async def test_fetch_exchange_params( + self, + exchange_servicer, + ): + spot_market_instant_listing_fee = coin_pb.Coin(denom="inj", amount="10000000000000000000") + derivative_market_instant_listing_fee = coin_pb.Coin(denom="inj", amount="2000000000000000000000") + binary_options_market_instant_listing_fee = coin_pb.Coin(denom="inj", amount="30000000000000000000") + params = exchange_pb.Params( + spot_market_instant_listing_fee=spot_market_instant_listing_fee, + derivative_market_instant_listing_fee=derivative_market_instant_listing_fee, + default_spot_maker_fee_rate="-0.000100000000000000", + default_spot_taker_fee_rate="0.001000000000000000", + default_derivative_maker_fee_rate="-0.000100000000000000", + default_derivative_taker_fee_rate="0.001000000000000000", + default_initial_margin_ratio="0.050000000000000000", + default_maintenance_margin_ratio="0.020000000000000000", + default_funding_interval=3600, + funding_multiple=4600, + relayer_fee_share_rate="0.400000000000000000", + default_hourly_funding_rate_cap="0.000625000000000000", + default_hourly_interest_rate="0.000004166660000000", + max_derivative_order_side_count=20, + inj_reward_staked_requirement_threshold="25000000000000000000", + trading_rewards_vesting_duration=1209600, + liquidator_reward_share_rate="0.050000000000000000", + binary_options_market_instant_listing_fee=binary_options_market_instant_listing_fee, + atomic_market_order_access_level=2, + spot_atomic_market_order_fee_multiplier="2.000000000000000000", + derivative_atomic_market_order_fee_multiplier="2.000000000000000000", + binary_options_atomic_market_order_fee_multiplier="2.000000000000000000", + minimal_protocol_fee_rate="0.000010000000000000", + is_instant_derivative_market_launch_enabled=False, + post_only_mode_height_threshold=57078000, + ) + exchange_servicer.exchange_params.append(exchange_query_pb.QueryExchangeParamsResponse(params=params)) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + module_params = await api.fetch_exchange_params() + expected_params = { + "params": { + "spotMarketInstantListingFee": { + "amount": spot_market_instant_listing_fee.amount, + "denom": spot_market_instant_listing_fee.denom, + }, + "derivativeMarketInstantListingFee": { + "amount": derivative_market_instant_listing_fee.amount, + "denom": derivative_market_instant_listing_fee.denom, + }, + "defaultSpotMakerFeeRate": params.default_spot_maker_fee_rate, + "defaultSpotTakerFeeRate": params.default_spot_taker_fee_rate, + "defaultDerivativeMakerFeeRate": params.default_derivative_maker_fee_rate, + "defaultDerivativeTakerFeeRate": params.default_derivative_taker_fee_rate, + "defaultInitialMarginRatio": params.default_initial_margin_ratio, + "defaultMaintenanceMarginRatio": params.default_maintenance_margin_ratio, + "defaultFundingInterval": str(params.default_funding_interval), + "fundingMultiple": str(params.funding_multiple), + "relayerFeeShareRate": params.relayer_fee_share_rate, + "defaultHourlyFundingRateCap": params.default_hourly_funding_rate_cap, + "defaultHourlyInterestRate": params.default_hourly_interest_rate, + "maxDerivativeOrderSideCount": params.max_derivative_order_side_count, + "injRewardStakedRequirementThreshold": params.inj_reward_staked_requirement_threshold, + "tradingRewardsVestingDuration": str(params.trading_rewards_vesting_duration), + "liquidatorRewardShareRate": "0.050000000000000000", + "binaryOptionsMarketInstantListingFee": { + "amount": binary_options_market_instant_listing_fee.amount, + "denom": binary_options_market_instant_listing_fee.denom, + }, + "atomicMarketOrderAccessLevel": exchange_pb.AtomicMarketOrderAccessLevel.Name( + params.atomic_market_order_access_level + ), + "spotAtomicMarketOrderFeeMultiplier": params.spot_atomic_market_order_fee_multiplier, + "derivativeAtomicMarketOrderFeeMultiplier": params.derivative_atomic_market_order_fee_multiplier, + "binaryOptionsAtomicMarketOrderFeeMultiplier": params.binary_options_atomic_market_order_fee_multiplier, + "minimalProtocolFeeRate": params.minimal_protocol_fee_rate, + "isInstantDerivativeMarketLaunchEnabled": params.is_instant_derivative_market_launch_enabled, + "postOnlyModeHeightThreshold": str(params.post_only_mode_height_threshold), + } + } + + assert module_params == expected_params + + @pytest.mark.asyncio + async def test_fetch_subaccount_deposits( + self, + exchange_servicer, + ): + deposit_denom = "inj" + deposit = exchange_pb.Deposit( + available_balance="1000000000000000000", + total_balance="2000000000000000000", + ) + exchange_servicer.subaccount_deposits_responses.append( + exchange_query_pb.QuerySubaccountDepositsResponse(deposits={deposit_denom: deposit}) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + deposits = await api.fetch_subaccount_deposits( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + subaccount_trader="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7", + subaccount_nonce=1, + ) + expected_deposits = { + "deposits": { + deposit_denom: { + "availableBalance": deposit.available_balance, + "totalBalance": deposit.total_balance, + }, + } + } + + assert deposits == expected_deposits + + @pytest.mark.asyncio + async def test_fetch_subaccount_deposit( + self, + exchange_servicer, + ): + deposit = exchange_pb.Deposit( + available_balance="1000000000000000000", + total_balance="2000000000000000000", + ) + exchange_servicer.subaccount_deposit_responses.append( + exchange_query_pb.QuerySubaccountDepositResponse(deposits=deposit) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + deposit_response = await api.fetch_subaccount_deposit( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="inj", + ) + expected_deposit = { + "deposits": { + "availableBalance": deposit.available_balance, + "totalBalance": deposit.total_balance, + } + } + + assert deposit_response == expected_deposit + + @pytest.mark.asyncio + async def test_fetch_exchange_balances( + self, + exchange_servicer, + ): + deposit = exchange_pb.Deposit( + available_balance="1000000000000000000", + total_balance="2000000000000000000", + ) + balance = genesis_pb.Balance( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="inj", + deposits=deposit, + ) + exchange_servicer.exchange_balances_responses.append( + exchange_query_pb.QueryExchangeBalancesResponse(balances=[balance]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + balances_response = await api.fetch_exchange_balances() + expected_balances = { + "balances": [ + { + "subaccountId": balance.subaccount_id, + "denom": balance.denom, + "deposits": { + "availableBalance": deposit.available_balance, + "totalBalance": deposit.total_balance, + }, + }, + ] + } + + assert balances_response == expected_balances + + @pytest.mark.asyncio + async def test_fetch_aggregate_volume( + self, + exchange_servicer, + ): + volume = exchange_pb.VolumeRecord( + maker_volume="1000000000000000000", + taker_volume="2000000000000000000", + ) + market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=volume, + ) + exchange_servicer.aggregate_volume_responses.append( + exchange_query_pb.QueryAggregateVolumeResponse( + aggregate_volumes=[market_volume], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_volume(account="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r") + expected_volume = { + "aggregateVolumes": [ + { + "marketId": market_volume.market_id, + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + }, + }, + ] + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_aggregate_volumes( + self, + exchange_servicer, + ): + acc_volume = exchange_pb.VolumeRecord( + maker_volume="1000000000000000000", + taker_volume="2000000000000000000", + ) + account_market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=acc_volume, + ) + account_volume = exchange_pb.AggregateAccountVolumeRecord( + account="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + market_volumes=[account_market_volume], + ) + volume = exchange_pb.VolumeRecord( + maker_volume="3000000000000000000", + taker_volume="4000000000000000000", + ) + market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=volume, + ) + exchange_servicer.aggregate_volumes_responses.append( + exchange_query_pb.QueryAggregateVolumesResponse( + aggregate_account_volumes=[account_volume], + aggregate_market_volumes=[market_volume], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_volumes( + accounts=[account_volume.account], + market_ids=[account_market_volume.market_id], + ) + expected_volume = { + "aggregateAccountVolumes": [ + { + "account": account_volume.account, + "marketVolumes": [ + { + "marketId": account_market_volume.market_id, + "volume": { + "makerVolume": acc_volume.maker_volume, + "takerVolume": acc_volume.taker_volume, + }, + }, + ], + }, + ], + "aggregateMarketVolumes": [ + { + "marketId": market_volume.market_id, + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + }, + }, + ], + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_aggregate_market_volume( + self, + exchange_servicer, + ): + volume = exchange_pb.VolumeRecord( + maker_volume="1000000000000000000", + taker_volume="2000000000000000000", + ) + exchange_servicer.aggregate_market_volume_responses.append( + exchange_query_pb.QueryAggregateMarketVolumeResponse( + volume=volume, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_market_volume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + ) + expected_volume = { + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + } + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_aggregate_market_volumes( + self, + exchange_servicer, + ): + volume = exchange_pb.VolumeRecord( + maker_volume="3000000000000000000", + taker_volume="4000000000000000000", + ) + market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=volume, + ) + exchange_servicer.aggregate_market_volumes_responses.append( + exchange_query_pb.QueryAggregateMarketVolumesResponse( + volumes=[market_volume], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_market_volumes( + market_ids=[market_volume.market_id], + ) + expected_volume = { + "volumes": [ + { + "marketId": market_volume.market_id, + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + }, + }, + ], + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_denom_decimal( + self, + exchange_servicer, + ): + decimal = 18 + exchange_servicer.denom_decimal_responses.append( + exchange_query_pb.QueryDenomDecimalResponse( + decimal=decimal, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + denom_decimal = await api.fetch_denom_decimal(denom="inj") + expected_decimal = {"decimal": str(decimal)} + + assert denom_decimal == expected_decimal + + @pytest.mark.asyncio + async def test_fetch_denom_decimals( + self, + exchange_servicer, + ): + denom_decimal = exchange_pb.DenomDecimals( + denom="inj", + decimals=18, + ) + exchange_servicer.denom_decimals_responses.append( + exchange_query_pb.QueryDenomDecimalsResponse( + denom_decimals=[denom_decimal], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + denom_decimals = await api.fetch_denom_decimals(denoms=[denom_decimal.denom]) + expected_decimals = { + "denomDecimals": [ + { + "denom": denom_decimal.denom, + "decimals": str(denom_decimal.decimals), + } + ] + } + + assert denom_decimals == expected_decimals + + @pytest.mark.asyncio + async def test_fetch_spot_markets( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + exchange_servicer.spot_markets_responses.append( + exchange_query_pb.QuerySpotMarketsResponse( + markets=[market], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + markets = await api.fetch_spot_markets( + status=status_string, + market_ids=[market.market_id], + ) + expected_markets = { + "markets": [ + { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + } + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_spot_market( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + exchange_servicer.spot_market_responses.append( + exchange_query_pb.QuerySpotMarketResponse( + market=market, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + response_market = await api.fetch_spot_market( + market_id=market.market_id, + ) + expected_market = { + "market": { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": exchange_pb.MarketStatus.Name(market.status), + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + } + } + + assert response_market == expected_market + + @pytest.mark.asyncio + async def test_fetch_full_spot_markets( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullSpotMarket( + market=market, + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.full_spot_markets_responses.append( + exchange_query_pb.QueryFullSpotMarketsResponse( + markets=[full_market], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + markets = await api.fetch_full_spot_markets( + status=status_string, + market_ids=[market.market_id], + with_mid_price_and_tob=True, + ) + expected_markets = { + "markets": [ + { + "market": { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_full_spot_market( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullSpotMarket( + market=market, + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.full_spot_market_responses.append( + exchange_query_pb.QueryFullSpotMarketResponse( + market=full_market, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + market_response = await api.fetch_full_spot_market( + market_id=market.market_id, + with_mid_price_and_tob=True, + ) + expected_market = { + "market": { + "market": { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + } + + assert market_response == expected_market + + @pytest.mark.asyncio + async def test_fetch_spot_orderbook( + self, + exchange_servicer, + ): + buy_price_level = exchange_pb.Level( + p="1000000000000000000", + q="1000000000000000", + ) + sell_price_level = exchange_pb.Level( + p="2000000000000000000", + q="2000000000000000", + ) + exchange_servicer.spot_orderbook_responses.append( + exchange_query_pb.QuerySpotOrderbookResponse( + buys_price_level=[buy_price_level], + sells_price_level=[sell_price_level], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orderbook = await api.fetch_spot_orderbook( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + order_side="Side_Unspecified", + limit_cumulative_notional="1000000000000000000", + limit_cumulative_quantity="1000000000000000", + pagination=PaginationOption(limit=100), + ) + expected_orderbook = { + "buysPriceLevel": [ + { + "p": buy_price_level.p, + "q": buy_price_level.q, + } + ], + "sellsPriceLevel": [ + { + "p": sell_price_level.p, + "q": sell_price_level.q, + } + ], + } + + assert orderbook == expected_orderbook + + @pytest.mark.asyncio + async def test_fetch_trader_spot_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_spot_orders_responses.append( + exchange_query_pb.QueryTraderSpotOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_account_address_spot_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.account_address_spot_orders_responses.append( + exchange_query_pb.QueryAccountAddressSpotOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_account_address_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + account_address="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_spot_orders_by_hashes( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.spot_orders_by_hashes_responses.append( + exchange_query_pb.QuerySpotOrdersByHashesResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_spot_orders_by_hashes( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + order_hashes=[order.order_hash], + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_subaccount_orders( + self, + exchange_servicer, + ): + buy_subaccount_order = exchange_pb.SubaccountOrder( + price="1000000000000000000", + quantity="1000000000000000", + isReduceOnly=False, + ) + buy_order = exchange_pb.SubaccountOrderData( + order=buy_subaccount_order, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849".encode(), + ) + sell_subaccount_order = exchange_pb.SubaccountOrder( + price="2000000000000000000", + quantity="2000000000000000", + isReduceOnly=False, + ) + sell_order = exchange_pb.SubaccountOrderData( + order=sell_subaccount_order, + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2".encode(), + ) + exchange_servicer.subaccount_orders_responses.append( + exchange_query_pb.QuerySubaccountOrdersResponse( + buy_orders=[buy_order], + sell_orders=[sell_order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_subaccount_orders( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + expected_orders = { + "buyOrders": [ + { + "order": { + "price": buy_subaccount_order.price, + "quantity": buy_subaccount_order.quantity, + "isReduceOnly": buy_subaccount_order.isReduceOnly, + }, + "orderHash": base64.b64encode(buy_order.order_hash).decode(), + } + ], + "sellOrders": [ + { + "order": { + "price": sell_subaccount_order.price, + "quantity": sell_subaccount_order.quantity, + "isReduceOnly": sell_subaccount_order.isReduceOnly, + }, + "orderHash": base64.b64encode(sell_order.order_hash).decode(), + } + ], + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_trader_spot_transient_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_spot_transient_orders_responses.append( + exchange_query_pb.QueryTraderSpotOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_spot_transient_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_spot_mid_price_and_tob( + self, + exchange_servicer, + ): + response = exchange_query_pb.QuerySpotMidPriceAndTOBResponse( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + exchange_servicer.spot_mid_price_and_tob_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + prices = await api.fetch_spot_mid_price_and_tob( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + expected_prices = { + "midPrice": response.mid_price, + "bestBuyPrice": response.best_buy_price, + "bestSellPrice": response.best_sell_price, + } + + assert prices == expected_prices + + @pytest.mark.asyncio + async def test_fetch_derivative_mid_price_and_tob( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryDerivativeMidPriceAndTOBResponse( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + exchange_servicer.derivative_mid_price_and_tob_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + prices = await api.fetch_derivative_mid_price_and_tob( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + expected_prices = { + "midPrice": response.mid_price, + "bestBuyPrice": response.best_buy_price, + "bestSellPrice": response.best_sell_price, + } + + assert prices == expected_prices + + @pytest.mark.asyncio + async def test_fetch_derivative_orderbook( + self, + exchange_servicer, + ): + buy_price_level = exchange_pb.Level( + p="1000000000000000000", + q="1000000000000000", + ) + sell_price_level = exchange_pb.Level( + p="2000000000000000000", + q="2000000000000000", + ) + exchange_servicer.derivative_orderbook_responses.append( + exchange_query_pb.QueryDerivativeOrderbookResponse( + buys_price_level=[buy_price_level], + sells_price_level=[sell_price_level], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orderbook = await api.fetch_derivative_orderbook( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + limit_cumulative_notional="1000000000000000000", + pagination=PaginationOption(limit=100), + ) + expected_orderbook = { + "buysPriceLevel": [ + { + "p": buy_price_level.p, + "q": buy_price_level.q, + } + ], + "sellsPriceLevel": [ + { + "p": sell_price_level.p, + "q": sell_price_level.q, + } + ], + } + + assert orderbook == expected_orderbook + + @pytest.mark.asyncio + async def test_fetch_trader_derivative_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_derivative_orders_responses.append( + exchange_query_pb.QueryTraderDerivativeOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_derivative_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_account_address_derivative_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.account_address_derivative_orders_responses.append( + exchange_query_pb.QueryAccountAddressDerivativeOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_account_address_derivative_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + account_address="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_derivative_orders_by_hashes( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.derivative_orders_by_hashes_responses.append( + exchange_query_pb.QueryDerivativeOrdersByHashesResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_derivative_orders_by_hashes( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + order_hashes=[order.order_hash], + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_trader_derivative_transient_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_derivative_transient_orders_responses.append( + exchange_query_pb.QueryTraderDerivativeOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_derivative_transient_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_derivative_markets( + self, + exchange_servicer, + ): + market = exchange_pb.DerivativeMarket( + ticker="20250608/USDT", + oracle_base="0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3", + oracle_quote="0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588", + oracle_type=9, + oracle_scale_factor=6, + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + initial_margin_ratio="50000000000000000", + maintenance_margin_ratio="20000000000000000", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="400000000000000000", + isPerpetual=True, + status=1, + min_price_tick_size="100000000000000000000", + min_quantity_tick_size="1000000000000000", + ) + market_info = exchange_pb.PerpetualMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + hourly_funding_rate_cap="625000000000000", + hourly_interest_rate="4166660000000", + next_funding_timestamp=1708099200, + funding_interval=3600, + ) + funding_info = exchange_pb.PerpetualMarketFunding( + cumulative_funding="-107853477278881692857461", + cumulative_price="0", + last_timestamp=1708099200, + ) + perpetual_info = exchange_query_pb.PerpetualMarketState( + market_info=market_info, + funding_info=funding_info, + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullDerivativeMarket( + market=market, + perpetual_info=perpetual_info, + mark_price="33803835513327368963000000", + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.derivative_markets_responses.append( + exchange_query_pb.QueryDerivativeMarketsResponse( + markets=[full_market], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + markets = await api.fetch_derivative_markets( + status=status_string, + market_ids=[market.market_id], + ) + expected_markets = { + "markets": [ + { + "market": { + "ticker": market.ticker, + "oracleBase": market.oracle_base, + "oracleQuote": market.oracle_quote, + "oracleType": oracle_pb.OracleType.Name(market.oracle_type), + "oracleScaleFactor": market.oracle_scale_factor, + "quoteDenom": market.quote_denom, + "marketId": market.market_id, + "initialMarginRatio": market.initial_margin_ratio, + "maintenanceMarginRatio": market.maintenance_margin_ratio, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "isPerpetual": market.isPerpetual, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "perpetualInfo": { + "marketInfo": { + "marketId": market_info.market_id, + "hourlyFundingRateCap": market_info.hourly_funding_rate_cap, + "hourlyInterestRate": market_info.hourly_interest_rate, + "nextFundingTimestamp": str(market_info.next_funding_timestamp), + "fundingInterval": str(market_info.funding_interval), + }, + "fundingInfo": { + "cumulativeFunding": funding_info.cumulative_funding, + "cumulativePrice": funding_info.cumulative_price, + "lastTimestamp": str(funding_info.last_timestamp), + }, + }, + "markPrice": full_market.mark_price, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_derivative_market( + self, + exchange_servicer, + ): + market = exchange_pb.DerivativeMarket( + ticker="INJ/USDT PERP", + oracle_base="0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3", + oracle_quote="0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588", + oracle_type=9, + oracle_scale_factor=6, + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + initial_margin_ratio="50000000000000000", + maintenance_margin_ratio="20000000000000000", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="400000000000000000", + isPerpetual=True, + status=1, + min_price_tick_size="100000000000000000000", + min_quantity_tick_size="1000000000000000", + ) + market_info = exchange_pb.PerpetualMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + hourly_funding_rate_cap="625000000000000", + hourly_interest_rate="4166660000000", + next_funding_timestamp=1708099200, + funding_interval=3600, + ) + funding_info = exchange_pb.PerpetualMarketFunding( + cumulative_funding="-107853477278881692857461", + cumulative_price="0", + last_timestamp=1708099200, + ) + perpetual_info = exchange_query_pb.PerpetualMarketState( + market_info=market_info, + funding_info=funding_info, + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullDerivativeMarket( + market=market, + perpetual_info=perpetual_info, + mark_price="33803835513327368963000000", + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.derivative_market_responses.append( + exchange_query_pb.QueryDerivativeMarketResponse( + market=full_market, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + market_response = await api.fetch_derivative_market( + market_id=market.market_id, + ) + expected_market = { + "market": { + "market": { + "ticker": market.ticker, + "oracleBase": market.oracle_base, + "oracleQuote": market.oracle_quote, + "oracleType": oracle_pb.OracleType.Name(market.oracle_type), + "oracleScaleFactor": market.oracle_scale_factor, + "quoteDenom": market.quote_denom, + "marketId": market.market_id, + "initialMarginRatio": market.initial_margin_ratio, + "maintenanceMarginRatio": market.maintenance_margin_ratio, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "isPerpetual": market.isPerpetual, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "perpetualInfo": { + "marketInfo": { + "marketId": market_info.market_id, + "hourlyFundingRateCap": market_info.hourly_funding_rate_cap, + "hourlyInterestRate": market_info.hourly_interest_rate, + "nextFundingTimestamp": str(market_info.next_funding_timestamp), + "fundingInterval": str(market_info.funding_interval), + }, + "fundingInfo": { + "cumulativeFunding": funding_info.cumulative_funding, + "cumulativePrice": funding_info.cumulative_price, + "lastTimestamp": str(funding_info.last_timestamp), + }, + }, + "markPrice": full_market.mark_price, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + } + + assert market_response == expected_market + + @pytest.mark.asyncio + async def test_fetch_derivative_market_address( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryDerivativeMarketAddressResponse( + address="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9", + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + ) + exchange_servicer.derivative_market_address_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + address = await api.fetch_derivative_market_address( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + expected_address = { + "address": response.address, + "subaccountId": response.subaccount_id, + } + + assert address == expected_address + + @pytest.mark.asyncio + async def test_fetch_subaccount_trade_nonce( + self, + exchange_servicer, + ): + response = exchange_query_pb.QuerySubaccountTradeNonceResponse(nonce=1234567879) + exchange_servicer.subaccount_trade_nonce_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + nonce = await api.fetch_subaccount_trade_nonce( + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + ) + expected_nonce = { + "nonce": response.nonce, + } + + assert nonce == expected_nonce + + @pytest.mark.asyncio + async def test_fetch_positions( + self, + exchange_servicer, + ): + position = exchange_pb.Position( + isLong=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + margin="2000000000000000000000000000000000", + cumulative_funding_entry="4000000", + ) + derivative_position = genesis_pb.DerivativePosition( + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + position=position, + ) + exchange_servicer.positions_responses.append( + exchange_query_pb.QueryPositionsResponse(state=[derivative_position]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + positions = await api.fetch_positions() + expected_positions = { + "state": [ + { + "subaccountId": derivative_position.subaccount_id, + "marketId": derivative_position.market_id, + "position": { + "isLong": position.isLong, + "quantity": position.quantity, + "entryPrice": position.entry_price, + "margin": position.margin, + "cumulativeFundingEntry": position.cumulative_funding_entry, + }, + }, + ], + } + + assert positions == expected_positions + + @pytest.mark.asyncio + async def test_fetch_subaccount_positions( + self, + exchange_servicer, + ): + position = exchange_pb.Position( + isLong=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + margin="2000000000000000000000000000000000", + cumulative_funding_entry="4000000", + ) + derivative_position = genesis_pb.DerivativePosition( + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + position=position, + ) + exchange_servicer.subaccount_positions_responses.append( + exchange_query_pb.QuerySubaccountPositionsResponse(state=[derivative_position]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + positions = await api.fetch_subaccount_positions(subaccount_id=derivative_position.subaccount_id) + expected_positions = { + "state": [ + { + "subaccountId": derivative_position.subaccount_id, + "marketId": derivative_position.market_id, + "position": { + "isLong": position.isLong, + "quantity": position.quantity, + "entryPrice": position.entry_price, + "margin": position.margin, + "cumulativeFundingEntry": position.cumulative_funding_entry, + }, + }, + ], + } + + assert positions == expected_positions + + @pytest.mark.asyncio + async def test_fetch_subaccount_position_in_market( + self, + exchange_servicer, + ): + subaccount_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000" + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + position = exchange_pb.Position( + isLong=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + margin="2000000000000000000000000000000000", + cumulative_funding_entry="4000000", + ) + exchange_servicer.subaccount_position_in_market_responses.append( + exchange_query_pb.QuerySubaccountPositionInMarketResponse(state=position) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + position_response = await api.fetch_subaccount_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + expected_position = { + "state": { + "isLong": position.isLong, + "quantity": position.quantity, + "entryPrice": position.entry_price, + "margin": position.margin, + "cumulativeFundingEntry": position.cumulative_funding_entry, + }, + } + + assert position_response == expected_position + + @pytest.mark.asyncio + async def test_fetch_subaccount_effective_position_in_market( + self, + exchange_servicer, + ): + subaccount_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000" + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + + effective_position = exchange_query_pb.EffectivePosition( + is_long=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + effective_margin="2000000000000000000000000000000000", + ) + exchange_servicer.subaccount_effective_position_in_market_responses.append( + exchange_query_pb.QuerySubaccountEffectivePositionInMarketResponse(state=effective_position) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + position_response = await api.fetch_subaccount_effective_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + expected_position = { + "state": { + "isLong": effective_position.is_long, + "quantity": effective_position.quantity, + "entryPrice": effective_position.entry_price, + "effectiveMargin": effective_position.effective_margin, + }, + } + + assert position_response == expected_position + + @pytest.mark.asyncio + async def test_fetch_perpetual_market_info( + self, + exchange_servicer, + ): + perpetual_market_info = exchange_pb.PerpetualMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + hourly_funding_rate_cap="625000000000000", + hourly_interest_rate="4166660000000", + next_funding_timestamp=1708099200, + funding_interval=3600, + ) + exchange_servicer.perpetual_market_info_responses.append( + exchange_query_pb.QueryPerpetualMarketInfoResponse(info=perpetual_market_info) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + market_info = await api.fetch_perpetual_market_info(market_id=perpetual_market_info.market_id) + expected_market_info = { + "info": { + "marketId": perpetual_market_info.market_id, + "hourlyFundingRateCap": perpetual_market_info.hourly_funding_rate_cap, + "hourlyInterestRate": perpetual_market_info.hourly_interest_rate, + "nextFundingTimestamp": str(perpetual_market_info.next_funding_timestamp), + "fundingInterval": str(perpetual_market_info.funding_interval), + } + } + + assert market_info == expected_market_info + + @pytest.mark.asyncio + async def test_fetch_expiry_futures_market_info( + self, + exchange_servicer, + ): + expiry_futures_market_info = exchange_pb.ExpiryFuturesMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + expiration_timestamp=1708099200, + twap_start_timestamp=1705566200, + expiration_twap_start_price_cumulative="1000000000000000000", + settlement_price="2000000000000000000", + ) + exchange_servicer.expiry_futures_market_info_responses.append( + exchange_query_pb.QueryExpiryFuturesMarketInfoResponse(info=expiry_futures_market_info) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + market_info = await api.fetch_expiry_futures_market_info(market_id=expiry_futures_market_info.market_id) + expected_market_info = { + "info": { + "marketId": expiry_futures_market_info.market_id, + "expirationTimestamp": str(expiry_futures_market_info.expiration_timestamp), + "twapStartTimestamp": str(expiry_futures_market_info.twap_start_timestamp), + "expirationTwapStartPriceCumulative": expiry_futures_market_info.expiration_twap_start_price_cumulative, + "settlementPrice": expiry_futures_market_info.settlement_price, + } + } + + assert market_info == expected_market_info + + @pytest.mark.asyncio + async def test_fetch_perpetual_market_funding( + self, + exchange_servicer, + ): + perpetual_market_funding = exchange_pb.PerpetualMarketFunding( + cumulative_funding="-107853477278881692857461", + cumulative_price="0", + last_timestamp=1708099200, + ) + exchange_servicer.perpetual_market_funding_responses.append( + exchange_query_pb.QueryPerpetualMarketFundingResponse(state=perpetual_market_funding) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + funding = await api.fetch_perpetual_market_funding( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + ) + expected_funding = { + "state": { + "cumulativeFunding": perpetual_market_funding.cumulative_funding, + "cumulativePrice": perpetual_market_funding.cumulative_price, + "lastTimestamp": str(perpetual_market_funding.last_timestamp), + } + } + + assert funding == expected_funding + + @pytest.mark.asyncio + async def test_fetch_subaccount_order_metadata( + self, + exchange_servicer, + ): + metadata = exchange_pb.SubaccountOrderbookMetadata( + vanilla_limit_order_count=1, + reduce_only_limit_order_count=2, + aggregate_reduce_only_quantity="1000000000000000", + aggregate_vanilla_quantity="2000000000000000", + vanilla_conditional_order_count=3, + reduce_only_conditional_order_count=4, + ) + subaccount_order_metadata = exchange_query_pb.SubaccountOrderbookMetadataWithMarket( + metadata=metadata, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + isBuy=True, + ) + exchange_servicer.subaccount_order_metadata_responses.append( + exchange_query_pb.QuerySubaccountOrderMetadataResponse(metadata=[subaccount_order_metadata]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + metadata_response = await api.fetch_subaccount_order_metadata( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001" + ) + expected_metadata = { + "metadata": [ + { + "metadata": { + "vanillaLimitOrderCount": metadata.vanilla_limit_order_count, + "reduceOnlyLimitOrderCount": metadata.reduce_only_limit_order_count, + "aggregateReduceOnlyQuantity": metadata.aggregate_reduce_only_quantity, + "aggregateVanillaQuantity": metadata.aggregate_vanilla_quantity, + "vanillaConditionalOrderCount": metadata.vanilla_conditional_order_count, + "reduceOnlyConditionalOrderCount": metadata.reduce_only_conditional_order_count, + }, + "marketId": subaccount_order_metadata.market_id, + "isBuy": subaccount_order_metadata.isBuy, + }, + ] + } + + assert metadata_response == expected_metadata + + @pytest.mark.asyncio + async def test_fetch_trade_reward_points( + self, + exchange_servicer, + ): + points = "40" + response = exchange_query_pb.QueryTradeRewardPointsResponse(account_trade_reward_points=[points]) + exchange_servicer.trade_reward_points_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + trade_reward_points = await api.fetch_trade_reward_points( + accounts=["inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"], + pending_pool_timestamp=1708099200, + ) + expected_trade_reward_points = {"accountTradeRewardPoints": [points]} + + assert trade_reward_points == expected_trade_reward_points + + @pytest.mark.asyncio + async def test_fetch_pending_trade_reward_points( + self, + exchange_servicer, + ): + points = "40" + response = exchange_query_pb.QueryTradeRewardPointsResponse(account_trade_reward_points=[points]) + exchange_servicer.pending_trade_reward_points_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + trade_reward_points = await api.fetch_pending_trade_reward_points( + accounts=["inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"], + pending_pool_timestamp=1708099200, + ) + expected_trade_reward_points = {"accountTradeRewardPoints": [points]} + + assert trade_reward_points == expected_trade_reward_points + + @pytest.mark.asyncio + async def test_fetch_fee_discount_account_info( + self, + exchange_servicer, + ): + account_info = exchange_pb.FeeDiscountTierInfo( + maker_discount_rate="0.0001", + taker_discount_rate="0.0002", + staked_amount="1000000000", + volume="1000000000000000000", + ) + account_ttl = exchange_pb.FeeDiscountTierTTL( + tier=3, + ttl_timestamp=1708099200, + ) + response = exchange_query_pb.QueryFeeDiscountAccountInfoResponse( + tier_level=3, + account_info=account_info, + account_ttl=account_ttl, + ) + exchange_servicer.fee_discount_account_info_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + fee_discount = await api.fetch_fee_discount_account_info(account="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r") + expected_fee_discount = { + "tierLevel": str(response.tier_level), + "accountInfo": { + "makerDiscountRate": account_info.maker_discount_rate, + "takerDiscountRate": account_info.taker_discount_rate, + "stakedAmount": account_info.staked_amount, + "volume": account_info.volume, + }, + "accountTtl": { + "tier": str(account_ttl.tier), + "ttlTimestamp": str(account_ttl.ttl_timestamp), + }, + } + + assert fee_discount == expected_fee_discount + + @pytest.mark.asyncio + async def test_fetch_fee_discount_schedule( + self, + exchange_servicer, + ): + fee_discount_tier_info = exchange_pb.FeeDiscountTierInfo( + maker_discount_rate="0.0001", + taker_discount_rate="0.0002", + staked_amount="1000000000", + volume="1000000000000000000", + ) + fee_discount_schedule = exchange_pb.FeeDiscountSchedule( + bucket_count=3, + bucket_duration=3600, + quote_denoms=["peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"], + tier_infos=[fee_discount_tier_info], + disqualified_market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"], + ) + exchange_servicer.fee_discount_schedule_responses.append( + exchange_query_pb.QueryFeeDiscountScheduleResponse( + fee_discount_schedule=fee_discount_schedule, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + schedule = await api.fetch_fee_discount_schedule() + expected_schedule = { + "feeDiscountSchedule": { + "bucketCount": str(fee_discount_schedule.bucket_count), + "bucketDuration": str(fee_discount_schedule.bucket_duration), + "quoteDenoms": fee_discount_schedule.quote_denoms, + "tierInfos": [ + { + "makerDiscountRate": fee_discount_tier_info.maker_discount_rate, + "takerDiscountRate": fee_discount_tier_info.taker_discount_rate, + "stakedAmount": fee_discount_tier_info.staked_amount, + "volume": fee_discount_tier_info.volume, + } + ], + "disqualifiedMarketIds": fee_discount_schedule.disqualified_market_ids, + }, + } + + assert schedule == expected_schedule + + @pytest.mark.asyncio + async def test_fetch_balance_mismatches( + self, + exchange_servicer, + ): + balance_mismatch = exchange_query_pb.BalanceMismatch( + subaccountId="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + available="1000000000000000", + total="2000000000000000", + balance_hold="3000000000000000", + expected_total="4000000000000000", + difference="500000000000000", + ) + exchange_servicer.balance_mismatches_responses.append( + exchange_query_pb.QueryBalanceMismatchesResponse( + balance_mismatches=[balance_mismatch], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + mismatches = await api.fetch_balance_mismatches(dust_factor=20) + expected_mismatches = { + "balanceMismatches": [ + { + "subaccountId": balance_mismatch.subaccountId, + "denom": balance_mismatch.denom, + "available": balance_mismatch.available, + "total": balance_mismatch.total, + "balanceHold": balance_mismatch.balance_hold, + "expectedTotal": balance_mismatch.expected_total, + "difference": balance_mismatch.difference, + } + ], + } + + assert mismatches == expected_mismatches + + @pytest.mark.asyncio + async def test_fetch_balance_with_balance_holds( + self, + exchange_servicer, + ): + balance_with_balance_hold = exchange_query_pb.BalanceWithMarginHold( + subaccountId="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + available="1000000000000000", + total="2000000000000000", + balance_hold="3000000000000000", + ) + exchange_servicer.balance_with_balance_holds_responses.append( + exchange_query_pb.QueryBalanceWithBalanceHoldsResponse( + balance_with_balance_holds=[balance_with_balance_hold], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + balance = await api.fetch_balance_with_balance_holds() + expected_balance = { + "balanceWithBalanceHolds": [ + { + "subaccountId": balance_with_balance_hold.subaccountId, + "denom": balance_with_balance_hold.denom, + "available": balance_with_balance_hold.available, + "total": balance_with_balance_hold.total, + "balanceHold": balance_with_balance_hold.balance_hold, + } + ], + } + + assert balance == expected_balance + + @pytest.mark.asyncio + async def test_fetch_fee_discount_tier_statistics( + self, + exchange_servicer, + ): + tier_statistics = exchange_query_pb.TierStatistic( + tier=3, + count=30, + ) + exchange_servicer.fee_discount_tier_statistics_responses.append( + exchange_query_pb.QueryFeeDiscountTierStatisticsResponse( + statistics=[tier_statistics], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + statistics = await api.fetch_fee_discount_tier_statistics() + expected_statistics = { + "statistics": [ + { + "tier": str(tier_statistics.tier), + "count": str(tier_statistics.count), + } + ], + } + + assert statistics == expected_statistics + + @pytest.mark.asyncio + async def test_fetch_mito_vault_infos( + self, + exchange_servicer, + ): + master_address = "inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9" + derivative_address = "inj1zlh5" + spot_address = "inj1zlh6" + cw20_address = "inj1zlh7" + response = exchange_query_pb.MitoVaultInfosResponse( + master_addresses=[master_address], + derivative_addresses=[derivative_address], + spot_addresses=[spot_address], + cw20_addresses=[cw20_address], + ) + exchange_servicer.mito_vault_infos_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + mito_vaults = await api.fetch_mito_vault_infos() + expected_mito_vaults = { + "masterAddresses": [master_address], + "derivativeAddresses": [derivative_address], + "spotAddresses": [spot_address], + "cw20Addresses": [cw20_address], + } + + assert mito_vaults == expected_mito_vaults + + @pytest.mark.asyncio + async def test_fetch_market_id_from_vault( + self, + exchange_servicer, + ): + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + exchange_servicer.market_id_from_vault_responses.append( + exchange_query_pb.QueryMarketIDFromVaultResponse( + market_id=market_id, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + market_id_response = await api.fetch_market_id_from_vault( + vault_address="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9" + ) + expected_market_id = { + "marketId": market_id, + } + + assert market_id_response == expected_market_id + + @pytest.mark.asyncio + async def test_fetch_historical_trade_records( + self, + exchange_servicer, + ): + latest_trade_record = exchange_pb.TradeRecord( + timestamp=1708099200, + price="2000000000000000000", + quantity="1000000000000000", + ) + trade_record = exchange_pb.TradeRecords( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + latest_trade_records=[latest_trade_record], + ) + exchange_servicer.historical_trade_records_responses.append( + exchange_query_pb.QueryHistoricalTradeRecordsResponse( + trade_records=[trade_record], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + records = await api.fetch_historical_trade_records(market_id=trade_record.market_id) + expected_records = { + "tradeRecords": [ + { + "marketId": trade_record.market_id, + "latestTradeRecords": [ + { + "timestamp": str(latest_trade_record.timestamp), + "price": latest_trade_record.price, + "quantity": latest_trade_record.quantity, + } + ], + }, + ], + } + + assert records == expected_records + + @pytest.mark.asyncio + async def test_fetch_is_opted_out_of_rewards( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryIsOptedOutOfRewardsResponse( + is_opted_out=False, + ) + exchange_servicer.is_opted_out_of_rewards_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + is_opted_out = await api.fetch_is_opted_out_of_rewards(account="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9") + expected_is_opted_out = { + "isOptedOut": response.is_opted_out, + } + + assert is_opted_out == expected_is_opted_out + + @pytest.mark.asyncio + async def test_fetch_opted_out_of_rewards_accounts( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryOptedOutOfRewardsAccountsResponse( + accounts=["inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9"], + ) + exchange_servicer.opted_out_of_rewards_accounts_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + opted_out = await api.fetch_opted_out_of_rewards_accounts() + expected_opted_out = { + "accounts": response.accounts, + } + + assert opted_out == expected_opted_out + + @pytest.mark.asyncio + async def test_fetch_market_volatility( + self, + exchange_servicer, + ): + history_metadata = oracle_pb.MetadataStatistics( + group_count=2, + records_sample_size=10, + mean="0.0001", + twap="0.0005", + first_timestamp=1702399200, + last_timestamp=1708099200, + min_price="1000000000000", + max_price="3000000000000", + median_price="2000000000000", + ) + trade_record = exchange_pb.TradeRecord( + timestamp=1708099200, + price="2000000000000000000", + quantity="1000000000000000", + ) + response = exchange_query_pb.QueryMarketVolatilityResponse( + volatility="0.0001", history_metadata=history_metadata, raw_history=[trade_record] + ) + exchange_servicer.market_volatility_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volatility = await api.fetch_market_volatility( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + trade_grouping_sec=0, + max_age=28000000, + include_raw_history=True, + include_metadata=True, + ) + expected_volatility = { + "volatility": response.volatility, + "historyMetadata": { + "groupCount": history_metadata.group_count, + "recordsSampleSize": history_metadata.records_sample_size, + "mean": history_metadata.mean, + "twap": history_metadata.twap, + "firstTimestamp": str(history_metadata.first_timestamp), + "lastTimestamp": str(history_metadata.last_timestamp), + "minPrice": history_metadata.min_price, + "maxPrice": history_metadata.max_price, + "medianPrice": history_metadata.median_price, + }, + "rawHistory": [ + { + "timestamp": str(trade_record.timestamp), + "price": trade_record.price, + "quantity": trade_record.quantity, + } + ], + } + + assert volatility == expected_volatility + + @pytest.mark.asyncio + async def test_fetch_binary_options_markets( + self, + exchange_servicer, + ): + market = exchange_pb.BinaryOptionsMarket( + ticker="20250608/USDT", + oracle_symbol="0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3", + oracle_provider="Pyth", + oracle_type=9, + oracle_scale_factor=6, + expiration_timestamp=1708099200, + settlement_timestamp=1707099200, + admin="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="400000000000000000", + status=1, + min_price_tick_size="100000000000000000000", + min_quantity_tick_size="1000000000000000", + settlement_price="2000000000000000000", + ) + response = exchange_query_pb.QueryBinaryMarketsResponse( + markets=[market], + ) + exchange_servicer.binary_options_markets_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + markets = await api.fetch_binary_options_markets(status="Active") + expected_markets = { + "markets": [ + { + "ticker": market.ticker, + "oracleSymbol": market.oracle_symbol, + "oracleProvider": market.oracle_provider, + "oracleType": oracle_pb.OracleType.Name(market.oracle_type), + "oracleScaleFactor": market.oracle_scale_factor, + "expirationTimestamp": str(market.expiration_timestamp), + "settlementTimestamp": str(market.settlement_timestamp), + "admin": market.admin, + "quoteDenom": market.quote_denom, + "marketId": market.market_id, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "status": exchange_pb.MarketStatus.Name(market.status), + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + "settlementPrice": market.settlement_price, + }, + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_trader_derivative_conditional_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeConditionalOrder( + price="2000000000000000000", + quantity="1000000000000000", + margin="2000000000000000000000000000000000", + triggerPrice="3000000000000000000", + isBuy=True, + isLimit=True, + order_hash="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + response = exchange_query_pb.QueryTraderDerivativeConditionalOrdersResponse(orders=[order]) + exchange_servicer.trader_derivative_conditional_orders_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_derivative_conditional_orders( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "triggerPrice": order.triggerPrice, + "isBuy": order.isBuy, + "isLimit": order.isLimit, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_market_atomic_execution_fee_multiplier( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryMarketAtomicExecutionFeeMultiplierResponse( + multiplier="100", + ) + exchange_servicer.market_atomic_execution_fee_multiplier_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + multiplier = await api.fetch_market_atomic_execution_fee_multiplier( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + expected_multiplier = { + "multiplier": response.multiplier, + } + + assert multiplier == expected_multiplier + + async def _dummy_metadata_provider(self): + return None From 96c79c023225db49ed8a07131385640b5f526f87 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 27 Feb 2024 10:03:11 -0300 Subject: [PATCH 19/44] (feat) Added support for all chain exchange module messages in Composer. Added unit tests for new messages. Refactored example scripts to move them into separated subfolders for each module. --- ..._LocalOrderHash.py => 1_LocalOrderHash.py} | 101 +- ...OrderFail.py => 2_StreamEventOrderFail.py} | 0 .../35_MsgInstantBinaryOptionsMarketLaunch.py | 98 - ...Broadcaster.py => 3_MessageBroadcaster.py} | 21 +- ...4_MessageBroadcasterWithGranteeAccount.py} | 12 +- ... 5_MessageBroadcasterWithoutSimulation.py} | 19 +- ...terWithGranteeAccountWithoutSimulation.py} | 12 +- .../{49_ChainStream.py => 7_ChainStream.py} | 0 .../{18_MsgBid.py => auction/1_MsgBid.py} | 0 .../query/1_Account.py} | 0 .../{19_MsgGrant.py => authz/1_MsgGrant.py} | 0 .../{20_MsgExec.py => authz/2_MsgExec.py} | 10 +- .../{21_MsgRevoke.py => authz/3_MsgRevoke.py} | 0 .../4_MsgExecuteContractCompat.py} | 0 .../{27_Grants.py => authz/query/1_Grants.py} | 0 examples/chain_client/{ => bank}/1_MsgSend.py | 0 .../query/10_SendEnabled.py} | 0 .../query/1_BankBalance.py} | 0 .../query/2_BankBalances.py} | 0 .../query/3_SpendableBalances.py} | 0 .../query/4_SpendableBalancesByDenom.py} | 0 .../query/5_TotalSupply.py} | 0 .../query/6_SupplyOf.py} | 0 .../query/7_DenomMetadata.py} | 0 .../query/8_DenomsMetadata.py} | 0 .../query/9_DenomOwners.py} | 0 ...py => 10_MsgCreateDerivativeLimitOrder.py} | 14 +- ...y => 11_MsgCreateDerivativeMarketOrder.py} | 12 +- ...rder.py => 12_MsgCancelDerivativeOrder.py} | 2 +- .../13_MsgInstantBinaryOptionsMarketLaunch.py | 61 + ...=> 14_MsgCreateBinaryOptionsLimitOrder.py} | 13 +- ...> 15_MsgCreateBinaryOptionsMarketOrder.py} | 12 +- ...r.py => 16_MsgCancelBinaryOptionsOrder.py} | 2 +- ...ransfer.py => 17_MsgSubaccountTransfer.py} | 5 +- ...lTransfer.py => 18_MsgExternalTransfer.py} | 5 +- .../exchange/19_MsgLiquidatePosition.py | 15 +- .../chain_client/exchange/1_MsgDeposit.py | 4 +- .../20_MsgIncreasePositionMargin.py} | 5 +- ...ewardsOptOut.py => 21_MsgRewardsOptOut.py} | 2 +- .../22_MsgAdminUpdateBinaryOptionsMarket.py} | 5 +- .../{9_MsgWithdraw.py => 2_MsgWithdraw.py} | 2 +- .../exchange/3_MsgInstantSpotMarketLaunch.py | 54 + .../4_MsgInstantPerpetualMarketLaunch.py | 61 + .../5_MsgInstantExpiryFuturesMarketLaunch.py | 62 + ...tOrder.py => 6_MsgCreateSpotLimitOrder.py} | 10 +- ...Order.py => 7_MsgCreateSpotMarketOrder.py} | 11 +- ...elSpotOrder.py => 8_MsgCancelSpotOrder.py} | 0 ...ateOrders.py => 9_MsgBatchUpdateOrders.py} | 53 +- .../1_MsgCreateInsuranceFund.py} | 0 .../2_MsgUnderwrite.py} | 0 .../3_MsgRequestRedemption.py} | 0 .../1_MsgRelayPriceFeedPrice.py} | 0 .../2_MsgRelayProviderPrices.py} | 0 .../1_MsgSendToEth.py} | 0 .../1_MsgDelegate.py} | 0 .../1_CreateDenom.py} | 0 .../2_MsgMint.py} | 0 .../3_MsgBurn.py} | 0 .../4_MsgChangeAdmin.py} | 0 .../5_MsgSetDenomMetadata.py} | 0 .../query/1_DenomAuthorityMetadata.py} | 0 .../query/2_DenomsFromCreator.py} | 0 .../query/3_TokenfactoryModuleState.py} | 0 .../{37_GetTx.py => tx/query/1_GetTx.py} | 0 .../1_MsgExecuteContract.py} | 0 .../query/10_ContractsByCreator.py} | 0 .../query/1_ContractInfo.py} | 0 .../query/2_ContractHistory.py} | 0 .../query/3_ContractsByCode.py} | 0 .../query/4_AllContractsState.py} | 0 .../query/5_RawContractState.py} | 0 .../query/6_SmartContractState.py} | 0 .../query/7_SmartContractCode.py} | 0 .../query/8_SmartContractCodes.py} | 0 .../query/9_SmartContractPinnedCodes.py} | 0 pyinjective/composer.py | 1751 +++++++++++++---- pyinjective/core/market.py | 11 + tests/core/test_gas_limit_estimator.py | 158 +- tests/core/test_market.py | 36 + ...essage_based_transaction_fee_calculator.py | 27 +- tests/test_composer.py | 1466 ++++++++++++-- tests/test_composer_deprecation_warnings.py | 522 +++++ tests/test_orderhash.py | 20 +- 83 files changed, 3740 insertions(+), 934 deletions(-) rename examples/chain_client/{0_LocalOrderHash.py => 1_LocalOrderHash.py} (75%) rename examples/chain_client/{38_StreamEventOrderFail.py => 2_StreamEventOrderFail.py} (100%) delete mode 100644 examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py rename examples/chain_client/{44_MessageBroadcaster.py => 3_MessageBroadcaster.py} (84%) rename examples/chain_client/{45_MessageBroadcasterWithGranteeAccount.py => 4_MessageBroadcasterWithGranteeAccount.py} (91%) rename examples/chain_client/{46_MessageBroadcasterWithoutSimulation.py => 5_MessageBroadcasterWithoutSimulation.py} (86%) rename examples/chain_client/{47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py => 6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py} (91%) rename examples/chain_client/{49_ChainStream.py => 7_ChainStream.py} (100%) rename examples/chain_client/{18_MsgBid.py => auction/1_MsgBid.py} (100%) rename examples/chain_client/{39_Account.py => auth/query/1_Account.py} (100%) rename examples/chain_client/{19_MsgGrant.py => authz/1_MsgGrant.py} (100%) rename examples/chain_client/{20_MsgExec.py => authz/2_MsgExec.py} (95%) rename examples/chain_client/{21_MsgRevoke.py => authz/3_MsgRevoke.py} (100%) rename examples/chain_client/{76_MsgExecuteContractCompat.py => authz/4_MsgExecuteContractCompat.py} (100%) rename examples/chain_client/{27_Grants.py => authz/query/1_Grants.py} (100%) rename examples/chain_client/{ => bank}/1_MsgSend.py (100%) rename examples/chain_client/{57_SendEnabled.py => bank/query/10_SendEnabled.py} (100%) rename examples/chain_client/{29_BankBalance.py => bank/query/1_BankBalance.py} (100%) rename examples/chain_client/{28_BankBalances.py => bank/query/2_BankBalances.py} (100%) rename examples/chain_client/{50_SpendableBalances.py => bank/query/3_SpendableBalances.py} (100%) rename examples/chain_client/{51_SpendableBalancesByDenom.py => bank/query/4_SpendableBalancesByDenom.py} (100%) rename examples/chain_client/{52_TotalSupply.py => bank/query/5_TotalSupply.py} (100%) rename examples/chain_client/{53_SupplyOf.py => bank/query/6_SupplyOf.py} (100%) rename examples/chain_client/{54_DenomMetadata.py => bank/query/7_DenomMetadata.py} (100%) rename examples/chain_client/{55_DenomsMetadata.py => bank/query/8_DenomsMetadata.py} (100%) rename examples/chain_client/{56_DenomOwners.py => bank/query/9_DenomOwners.py} (100%) rename examples/chain_client/exchange/{6_MsgCreateDerivativeLimitOrder.py => 10_MsgCreateDerivativeLimitOrder.py} (90%) rename examples/chain_client/exchange/{7_MsgCreateDerivativeMarketOrder.py => 11_MsgCreateDerivativeMarketOrder.py} (90%) rename examples/chain_client/exchange/{8_MsgCancelDerivativeOrder.py => 12_MsgCancelDerivativeOrder.py} (98%) create mode 100644 examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py rename examples/chain_client/exchange/{16_MsgCreateBinaryOptionsLimitOrder.py => 14_MsgCreateBinaryOptionsLimitOrder.py} (93%) rename examples/chain_client/exchange/{17_MsgCreateBinaryOptionsMarketOrder.py => 15_MsgCreateBinaryOptionsMarketOrder.py} (90%) rename examples/chain_client/exchange/{18_MsgCancelBinaryOptionsOrder.py => 16_MsgCancelBinaryOptionsOrder.py} (98%) rename examples/chain_client/exchange/{10_MsgSubaccountTransfer.py => 17_MsgSubaccountTransfer.py} (96%) rename examples/chain_client/exchange/{15_ExternalTransfer.py => 18_MsgExternalTransfer.py} (96%) rename examples/chain_client/{13_MsgIncreasePositionMargin.py => exchange/20_MsgIncreasePositionMargin.py} (96%) rename examples/chain_client/exchange/{12_MsgRewardsOptOut.py => 21_MsgRewardsOptOut.py} (97%) rename examples/chain_client/{34_MsgAdminUpdateBinaryOptionsMarket.py => exchange/22_MsgAdminUpdateBinaryOptionsMarket.py} (96%) rename examples/chain_client/exchange/{9_MsgWithdraw.py => 2_MsgWithdraw.py} (95%) create mode 100644 examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py create mode 100644 examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py create mode 100644 examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py rename examples/chain_client/exchange/{3_MsgCreateSpotLimitOrder.py => 6_MsgCreateSpotLimitOrder.py} (94%) rename examples/chain_client/exchange/{4_MsgCreateSpotMarketOrder.py => 7_MsgCreateSpotMarketOrder.py} (94%) rename examples/chain_client/exchange/{5_MsgCancelSpotOrder.py => 8_MsgCancelSpotOrder.py} (100%) rename examples/chain_client/exchange/{11_MsgBatchUpdateOrders.py => 9_MsgBatchUpdateOrders.py} (83%) rename examples/chain_client/{41_MsgCreateInsuranceFund.py => insurance/1_MsgCreateInsuranceFund.py} (100%) rename examples/chain_client/{42_MsgUnderwrite.py => insurance/2_MsgUnderwrite.py} (100%) rename examples/chain_client/{43_MsgRequestRedemption.py => insurance/3_MsgRequestRedemption.py} (100%) rename examples/chain_client/{23_MsgRelayPriceFeedPrice.py => oracle/1_MsgRelayPriceFeedPrice.py} (100%) rename examples/chain_client/{36_MsgRelayProviderPrices.py => oracle/2_MsgRelayProviderPrices.py} (100%) rename examples/chain_client/{22_MsgSendToEth.py => peggy/1_MsgSendToEth.py} (100%) rename examples/chain_client/{25_MsgDelegate.py => staking/1_MsgDelegate.py} (100%) rename examples/chain_client/{71_CreateDenom.py => tokenfactory/1_CreateDenom.py} (100%) rename examples/chain_client/{72_MsgMint.py => tokenfactory/2_MsgMint.py} (100%) rename examples/chain_client/{73_MsgBurn.py => tokenfactory/3_MsgBurn.py} (100%) rename examples/chain_client/{75_MsgChangeAdmin.py => tokenfactory/4_MsgChangeAdmin.py} (100%) rename examples/chain_client/{74_MsgSetDenomMetadata.py => tokenfactory/5_MsgSetDenomMetadata.py} (100%) rename examples/chain_client/{68_DenomAuthorityMetadata.py => tokenfactory/query/1_DenomAuthorityMetadata.py} (100%) rename examples/chain_client/{69_DenomsFromCreator.py => tokenfactory/query/2_DenomsFromCreator.py} (100%) rename examples/chain_client/{70_TokenfactoryModuleState.py => tokenfactory/query/3_TokenfactoryModuleState.py} (100%) rename examples/chain_client/{37_GetTx.py => tx/query/1_GetTx.py} (100%) rename examples/chain_client/{40_MsgExecuteContract.py => wasm/1_MsgExecuteContract.py} (100%) rename examples/chain_client/{67_ContractsByCreator.py => wasm/query/10_ContractsByCreator.py} (100%) rename examples/chain_client/{58_ContractInfo.py => wasm/query/1_ContractInfo.py} (100%) rename examples/chain_client/{59_ContractHistory.py => wasm/query/2_ContractHistory.py} (100%) rename examples/chain_client/{60_ContractsByCode.py => wasm/query/3_ContractsByCode.py} (100%) rename examples/chain_client/{61_AllContractsState.py => wasm/query/4_AllContractsState.py} (100%) rename examples/chain_client/{62_RawContractState.py => wasm/query/5_RawContractState.py} (100%) rename examples/chain_client/{63_SmartContractState.py => wasm/query/6_SmartContractState.py} (100%) rename examples/chain_client/{64_SmartContractCode.py => wasm/query/7_SmartContractCode.py} (100%) rename examples/chain_client/{65_SmartContractCodes.py => wasm/query/8_SmartContractCodes.py} (100%) rename examples/chain_client/{66_SmartContractPinnedCodes.py => wasm/query/9_SmartContractPinnedCodes.py} (100%) create mode 100644 tests/test_composer_deprecation_warnings.py diff --git a/examples/chain_client/0_LocalOrderHash.py b/examples/chain_client/1_LocalOrderHash.py similarity index 75% rename from examples/chain_client/0_LocalOrderHash.py rename to examples/chain_client/1_LocalOrderHash.py index 770ad5bf..fbec8988 100644 --- a/examples/chain_client/0_LocalOrderHash.py +++ b/examples/chain_client/1_LocalOrderHash.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -40,57 +41,59 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" spot_orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.524, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("0.524"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=27.92, - quantity=0.01, - is_buy=False, - is_po=False, + price=Decimal("27.92"), + quantity=Decimal("0.01"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] derivative_orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=10500, - quantity=0.01, - leverage=1.5, - is_buy=True, - is_po=False, + price=Decimal(10500), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(10500), leverage=Decimal(2), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=65111, - quantity=0.01, - leverage=2, - is_buy=False, - is_reduce_only=False, + price=Decimal(65111), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(65111), leverage=Decimal(2), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ), ] # prepare tx msg - spot_msg = composer.MsgBatchCreateSpotLimitOrders(sender=address.to_acc_bech32(), orders=spot_orders) + spot_msg = composer.msg_batch_create_spot_limit_orders(sender=address.to_acc_bech32(), orders=spot_orders) - deriv_msg = composer.MsgBatchCreateDerivativeLimitOrders(sender=address.to_acc_bech32(), orders=derivative_orders) + deriv_msg = composer.msg_batch_create_derivative_limit_orders( + sender=address.to_acc_bech32(), orders=derivative_orders + ) # compute order hashes order_hashes = order_hash_manager.compute_order_hashes( @@ -167,57 +170,59 @@ async def main() -> None: print("gas fee: {} INJ".format(gas_fee)) spot_orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=1.524, - quantity=0.01, - is_buy=True, - is_po=True, + price=Decimal("1.524"), + quantity=Decimal("0.01"), + order_type="BUY_PO", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=27.92, - quantity=0.01, - is_buy=False, - is_po=False, + price=Decimal("27.92"), + quantity=Decimal("0.01"), + order_type="SELL_PO", cid=str(uuid.uuid4()), ), ] derivative_orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=25111, - quantity=0.01, - leverage=1.5, - is_buy=True, - is_po=False, + price=Decimal(25111), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(25111), leverage=Decimal("1.5"), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=65111, - quantity=0.01, - leverage=2, - is_buy=False, - is_reduce_only=False, + price=Decimal(65111), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(25111), leverage=Decimal(2), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ), ] # prepare tx msg - spot_msg = composer.MsgBatchCreateSpotLimitOrders(sender=address.to_acc_bech32(), orders=spot_orders) + spot_msg = composer.msg_batch_create_spot_limit_orders(sender=address.to_acc_bech32(), orders=spot_orders) - deriv_msg = composer.MsgBatchCreateDerivativeLimitOrders(sender=address.to_acc_bech32(), orders=derivative_orders) + deriv_msg = composer.msg_batch_create_derivative_limit_orders( + sender=address.to_acc_bech32(), orders=derivative_orders + ) # compute order hashes order_hashes = order_hash_manager.compute_order_hashes( diff --git a/examples/chain_client/38_StreamEventOrderFail.py b/examples/chain_client/2_StreamEventOrderFail.py similarity index 100% rename from examples/chain_client/38_StreamEventOrderFail.py rename to examples/chain_client/2_StreamEventOrderFail.py diff --git a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py deleted file mode 100644 index 7b8a6567..00000000 --- a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py +++ /dev/null @@ -1,98 +0,0 @@ -import asyncio -import os - -import dotenv -from grpc import RpcError - -from pyinjective.async_client import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE -from pyinjective.core.network import Network -from pyinjective.transaction import Transaction -from pyinjective.wallet import PrivateKey - - -async def main() -> None: - dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") - - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - composer = await client.composer() - await client.sync_timeout_height() - - # load account - priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - # prepare tx msg - msg = composer.MsgInstantBinaryOptionsMarketLaunch( - sender=address.to_acc_bech32(), - admin=address.to_acc_bech32(), - ticker="UFC-KHABIB-TKO-05/30/2023", - oracle_symbol="UFC-KHABIB-TKO-05/30/2023", - oracle_provider="UFC", - oracle_type="Provider", - quote_denom="peggy0xdAC17F958D2ee523a2206206994597C13D831ec7", - quote_decimals=6, - oracle_scale_factor=6, - maker_fee_rate=0.0005, # 0.05% - taker_fee_rate=0.0010, # 0.10% - expiration_timestamp=1680730982, - settlement_timestamp=1690730982, - min_price_tick_size=0.01, - min_quantity_tick_size=0.01, - ) - - # build sim tx - tx = ( - Transaction() - .with_messages(msg) - .with_sequence(client.get_sequence()) - .with_account_num(client.get_number()) - .with_chain_id(network.chain_id) - ) - sim_sign_doc = tx.get_sign_doc(pub_key) - sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) - sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key) - - # simulate tx - try: - sim_res = await client.simulate(sim_tx_raw_bytes) - except RpcError as ex: - print(ex) - return - - sim_res_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) - - # build tx - gas_price = GAS_PRICE - gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation - gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") - fee = [ - composer.coin( - amount=gas_price * gas_limit, - denom=network.fee_denom, - ) - ] - tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height) - sign_doc = tx.get_sign_doc(pub_key) - sig = priv_key.sign(sign_doc.SerializeToString()) - tx_raw_bytes = tx.get_tx_data(sig, pub_key) - - # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode - res = await client.broadcast_tx_sync_mode(tx_raw_bytes) - print("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/44_MessageBroadcaster.py b/examples/chain_client/3_MessageBroadcaster.py similarity index 84% rename from examples/chain_client/44_MessageBroadcaster.py rename to examples/chain_client/3_MessageBroadcaster.py index 114a8700..6bd67033 100644 --- a/examples/chain_client/44_MessageBroadcaster.py +++ b/examples/chain_client/3_MessageBroadcaster.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -34,24 +35,22 @@ async def main() -> None: spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" spot_orders_to_create = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=3, - quantity=55, - is_buy=True, - is_po=False, - cid=str(uuid.uuid4()), + price=Decimal("3"), + quantity=Decimal("55"), + order_type="BUY", + cid=(str(uuid.uuid4())), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=300, - quantity=55, - is_buy=False, - is_po=False, + price=Decimal("300"), + quantity=Decimal("55"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] diff --git a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py b/examples/chain_client/4_MessageBroadcasterWithGranteeAccount.py similarity index 91% rename from examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py rename to examples/chain_client/4_MessageBroadcasterWithGranteeAccount.py index 8c0166e2..4e08397b 100644 --- a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py +++ b/examples/chain_client/4_MessageBroadcasterWithGranteeAccount.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -40,15 +41,14 @@ async def main() -> None: granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) - msg = composer.MsgCreateSpotLimitOrder( - sender=granter_inj_address, + msg = composer.msg_create_spot_limit_order( market_id=market_id, + sender=granter_inj_address, subaccount_id=granter_subaccount_id, fee_recipient=address.to_acc_bech32(), - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py b/examples/chain_client/5_MessageBroadcasterWithoutSimulation.py similarity index 86% rename from examples/chain_client/46_MessageBroadcasterWithoutSimulation.py rename to examples/chain_client/5_MessageBroadcasterWithoutSimulation.py index e6e87c5a..54a79bf8 100644 --- a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py +++ b/examples/chain_client/5_MessageBroadcasterWithoutSimulation.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -34,24 +35,22 @@ async def main() -> None: spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" spot_orders_to_create = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=3, - quantity=55, - is_buy=True, - is_po=False, + price=Decimal("3"), + quantity=Decimal("55"), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=300, - quantity=55, - is_buy=False, - is_po=False, + price=Decimal("300"), + quantity=Decimal("55"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] diff --git a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py b/examples/chain_client/6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py similarity index 91% rename from examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py rename to examples/chain_client/6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py index b95114b7..4b7fbd2e 100644 --- a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py +++ b/examples/chain_client/6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -39,15 +40,14 @@ async def main() -> None: granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) - msg = composer.MsgCreateSpotLimitOrder( - sender=granter_inj_address, + msg = composer.msg_create_spot_limit_order( market_id=market_id, + sender=granter_inj_address, subaccount_id=granter_subaccount_id, fee_recipient=address.to_acc_bech32(), - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/49_ChainStream.py b/examples/chain_client/7_ChainStream.py similarity index 100% rename from examples/chain_client/49_ChainStream.py rename to examples/chain_client/7_ChainStream.py diff --git a/examples/chain_client/18_MsgBid.py b/examples/chain_client/auction/1_MsgBid.py similarity index 100% rename from examples/chain_client/18_MsgBid.py rename to examples/chain_client/auction/1_MsgBid.py diff --git a/examples/chain_client/39_Account.py b/examples/chain_client/auth/query/1_Account.py similarity index 100% rename from examples/chain_client/39_Account.py rename to examples/chain_client/auth/query/1_Account.py diff --git a/examples/chain_client/19_MsgGrant.py b/examples/chain_client/authz/1_MsgGrant.py similarity index 100% rename from examples/chain_client/19_MsgGrant.py rename to examples/chain_client/authz/1_MsgGrant.py diff --git a/examples/chain_client/20_MsgExec.py b/examples/chain_client/authz/2_MsgExec.py similarity index 95% rename from examples/chain_client/20_MsgExec.py rename to examples/chain_client/authz/2_MsgExec.py index 1203ff90..8d9891a5 100644 --- a/examples/chain_client/20_MsgExec.py +++ b/examples/chain_client/authz/2_MsgExec.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -37,15 +38,14 @@ async def main() -> None: granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) - msg0 = composer.MsgCreateSpotLimitOrder( + msg0 = composer.msg_create_spot_limit_order( sender=granter_inj_address, market_id=market_id, subaccount_id=granter_subaccount_id, fee_recipient=grantee, - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/21_MsgRevoke.py b/examples/chain_client/authz/3_MsgRevoke.py similarity index 100% rename from examples/chain_client/21_MsgRevoke.py rename to examples/chain_client/authz/3_MsgRevoke.py diff --git a/examples/chain_client/76_MsgExecuteContractCompat.py b/examples/chain_client/authz/4_MsgExecuteContractCompat.py similarity index 100% rename from examples/chain_client/76_MsgExecuteContractCompat.py rename to examples/chain_client/authz/4_MsgExecuteContractCompat.py diff --git a/examples/chain_client/27_Grants.py b/examples/chain_client/authz/query/1_Grants.py similarity index 100% rename from examples/chain_client/27_Grants.py rename to examples/chain_client/authz/query/1_Grants.py diff --git a/examples/chain_client/1_MsgSend.py b/examples/chain_client/bank/1_MsgSend.py similarity index 100% rename from examples/chain_client/1_MsgSend.py rename to examples/chain_client/bank/1_MsgSend.py diff --git a/examples/chain_client/57_SendEnabled.py b/examples/chain_client/bank/query/10_SendEnabled.py similarity index 100% rename from examples/chain_client/57_SendEnabled.py rename to examples/chain_client/bank/query/10_SendEnabled.py diff --git a/examples/chain_client/29_BankBalance.py b/examples/chain_client/bank/query/1_BankBalance.py similarity index 100% rename from examples/chain_client/29_BankBalance.py rename to examples/chain_client/bank/query/1_BankBalance.py diff --git a/examples/chain_client/28_BankBalances.py b/examples/chain_client/bank/query/2_BankBalances.py similarity index 100% rename from examples/chain_client/28_BankBalances.py rename to examples/chain_client/bank/query/2_BankBalances.py diff --git a/examples/chain_client/50_SpendableBalances.py b/examples/chain_client/bank/query/3_SpendableBalances.py similarity index 100% rename from examples/chain_client/50_SpendableBalances.py rename to examples/chain_client/bank/query/3_SpendableBalances.py diff --git a/examples/chain_client/51_SpendableBalancesByDenom.py b/examples/chain_client/bank/query/4_SpendableBalancesByDenom.py similarity index 100% rename from examples/chain_client/51_SpendableBalancesByDenom.py rename to examples/chain_client/bank/query/4_SpendableBalancesByDenom.py diff --git a/examples/chain_client/52_TotalSupply.py b/examples/chain_client/bank/query/5_TotalSupply.py similarity index 100% rename from examples/chain_client/52_TotalSupply.py rename to examples/chain_client/bank/query/5_TotalSupply.py diff --git a/examples/chain_client/53_SupplyOf.py b/examples/chain_client/bank/query/6_SupplyOf.py similarity index 100% rename from examples/chain_client/53_SupplyOf.py rename to examples/chain_client/bank/query/6_SupplyOf.py diff --git a/examples/chain_client/54_DenomMetadata.py b/examples/chain_client/bank/query/7_DenomMetadata.py similarity index 100% rename from examples/chain_client/54_DenomMetadata.py rename to examples/chain_client/bank/query/7_DenomMetadata.py diff --git a/examples/chain_client/55_DenomsMetadata.py b/examples/chain_client/bank/query/8_DenomsMetadata.py similarity index 100% rename from examples/chain_client/55_DenomsMetadata.py rename to examples/chain_client/bank/query/8_DenomsMetadata.py diff --git a/examples/chain_client/56_DenomOwners.py b/examples/chain_client/bank/query/9_DenomOwners.py similarity index 100% rename from examples/chain_client/56_DenomOwners.py rename to examples/chain_client/bank/query/9_DenomOwners.py diff --git a/examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py similarity index 90% rename from examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py rename to examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py index 41a19307..4e0ff327 100644 --- a/examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,16 +37,17 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateDerivativeLimitOrder( + msg = composer.msg_create_derivative_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=50000, - quantity=0.1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(50000), + quantity=Decimal(0.1), + margin=composer.calculate_margin( + quantity=Decimal(0.1), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py similarity index 90% rename from examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py rename to examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py index 37b305ed..dfedf6d6 100644 --- a/examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py +++ b/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,15 +37,16 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateDerivativeMarketOrder( + msg = composer.msg_create_derivative_market_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=50000, - quantity=0.01, - leverage=3, - is_buy=True, + price=Decimal(50000), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(50000), leverage=Decimal(3), is_reduce_only=False + ), cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py b/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py similarity index 98% rename from examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py rename to examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py index 43180b1f..20be2bd0 100644 --- a/examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py +++ b/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py @@ -35,7 +35,7 @@ async def main() -> None: order_hash = "0x667ee6f37f6d06bf473f4e1434e92ac98ff43c785405e2a511a0843daeca2de9" # prepare tx msg - msg = composer.MsgCancelDerivativeOrder( + msg = composer.msg_cancel_derivative_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash ) diff --git a/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py new file mode 100644 index 00000000..a1ebde82 --- /dev/null +++ b/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py @@ -0,0 +1,61 @@ +import asyncio +import os + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + composer = await client.composer() + await client.sync_timeout_height() + + message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( + network=network, + private_key=configured_private_key, + ) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + message = composer.msg_instant_binary_options_market_launch( + sender=address.to_acc_bech32(), + ticker="UFC-KHABIB-TKO-05/30/2023", + oracle_symbol="UFC-KHABIB-TKO-05/30/2023", + oracle_provider="UFC", + oracle_type="Provider", + quote_decimals=6, + oracle_scale_factor=6, + maker_fee_rate=0.0005, # 0.05% + taker_fee_rate=0.0010, # 0.10% + expiration_timestamp=1680730982, + settlement_timestamp=1690730982, + admin=address.to_acc_bech32(), + quote_denom="peggy0xdAC17F958D2ee523a2206206994597C13D831ec7", + min_price_tick_size=0.01, + min_quantity_tick_size=0.01, + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py similarity index 93% rename from examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py rename to examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py index 2a58e173..5ad8c59e 100644 --- a/examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py +++ b/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -40,17 +41,17 @@ async def main() -> None: denom = Denom(description="desc", base=0, quote=6, min_price_tick_size=1000, min_quantity_tick_size=0.0001) # prepare tx msg - msg = composer.MsgCreateBinaryOptionsLimitOrder( + msg = composer.msg_create_binary_options_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.5, - quantity=1, - is_buy=False, - is_reduce_only=False, - denom=denom, + price=Decimal("0.5"), + quantity=Decimal("1"), + margin=Decimal("0.5"), + order_type="BUY", cid=str(uuid.uuid4()), + denom=denom, ) # build sim tx diff --git a/examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py similarity index 90% rename from examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py rename to examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py index 2d07658f..9b68bc85 100644 --- a/examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py +++ b/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,15 +37,16 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateBinaryOptionsMarketOrder( + msg = composer.msg_create_binary_options_market_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.5, - quantity=1, - is_buy=True, - is_reduce_only=False, + price=Decimal("0.5"), + quantity=Decimal(1), + margin=composer.calculate_margin( + quantity=Decimal(1), price=Decimal("0.5"), leverage=Decimal(1), is_reduce_only=False + ), cid=str(uuid.uuid4()), ) # build sim tx diff --git a/examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py similarity index 98% rename from examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py rename to examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py index 82107f3c..582c6dc6 100644 --- a/examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py +++ b/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py @@ -35,7 +35,7 @@ async def main() -> None: order_hash = "a975fbd72b874bdbf5caf5e1e8e2653937f33ce6dd14d241c06c8b1f7b56be46" # prepare tx msg - msg = composer.MsgCancelBinaryOptionsOrder( + msg = composer.msg_cancel_binary_options_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash ) # build sim tx diff --git a/examples/chain_client/exchange/10_MsgSubaccountTransfer.py b/examples/chain_client/exchange/17_MsgSubaccountTransfer.py similarity index 96% rename from examples/chain_client/exchange/10_MsgSubaccountTransfer.py rename to examples/chain_client/exchange/17_MsgSubaccountTransfer.py index b68717b2..a50fc0cf 100644 --- a/examples/chain_client/exchange/10_MsgSubaccountTransfer.py +++ b/examples/chain_client/exchange/17_MsgSubaccountTransfer.py @@ -1,5 +1,6 @@ import asyncio import os +from decimal import Decimal import dotenv from grpc import RpcError @@ -32,11 +33,11 @@ async def main() -> None: dest_subaccount_id = address.get_subaccount_id(index=1) # prepare tx msg - msg = composer.MsgSubaccountTransfer( + msg = composer.msg_subaccount_transfer( sender=address.to_acc_bech32(), source_subaccount_id=subaccount_id, destination_subaccount_id=dest_subaccount_id, - amount=100, + amount=Decimal(100), denom="INJ", ) diff --git a/examples/chain_client/exchange/15_ExternalTransfer.py b/examples/chain_client/exchange/18_MsgExternalTransfer.py similarity index 96% rename from examples/chain_client/exchange/15_ExternalTransfer.py rename to examples/chain_client/exchange/18_MsgExternalTransfer.py index 3200be34..2bcc86a1 100644 --- a/examples/chain_client/exchange/15_ExternalTransfer.py +++ b/examples/chain_client/exchange/18_MsgExternalTransfer.py @@ -1,5 +1,6 @@ import asyncio import os +from decimal import Decimal import dotenv from grpc import RpcError @@ -32,11 +33,11 @@ async def main() -> None: dest_subaccount_id = "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000" # prepare tx msg - msg = composer.MsgExternalTransfer( + msg = composer.msg_external_transfer( sender=address.to_acc_bech32(), source_subaccount_id=subaccount_id, destination_subaccount_id=dest_subaccount_id, - amount=100, + amount=Decimal(100), denom="INJ", ) diff --git a/examples/chain_client/exchange/19_MsgLiquidatePosition.py b/examples/chain_client/exchange/19_MsgLiquidatePosition.py index d80ba385..9788b865 100644 --- a/examples/chain_client/exchange/19_MsgLiquidatePosition.py +++ b/examples/chain_client/exchange/19_MsgLiquidatePosition.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,19 +37,21 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" cid = str(uuid.uuid4()) - order = composer.DerivativeOrder( + order = composer.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=39.01, # This should be the liquidation price - quantity=0.147, - leverage=1, + price=Decimal(39.01), # This should be the liquidation price + quantity=Decimal(0.147), + margin=composer.calculate_margin( + quantity=Decimal(0.147), price=Decimal(39.01), leverage=Decimal(1), is_reduce_only=False + ), + order_type="SELL", cid=cid, - is_buy=False, ) # prepare tx msg - msg = composer.MsgLiquidatePosition( + msg = composer.msg_liquidate_position( sender=address.to_acc_bech32(), subaccount_id="0x156df4d5bc8e7dd9191433e54bd6a11eeb390921000000000000000000000000", market_id=market_id, diff --git a/examples/chain_client/exchange/1_MsgDeposit.py b/examples/chain_client/exchange/1_MsgDeposit.py index 80b9f652..bbf64710 100644 --- a/examples/chain_client/exchange/1_MsgDeposit.py +++ b/examples/chain_client/exchange/1_MsgDeposit.py @@ -31,7 +31,9 @@ async def main() -> None: subaccount_id = address.get_subaccount_id(index=0) # prepare tx msg - msg = composer.MsgDeposit(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=0.000001, denom="INJ") + msg = composer.msg_deposit( + sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=0.000001, denom="INJ" + ) # build sim tx tx = ( diff --git a/examples/chain_client/13_MsgIncreasePositionMargin.py b/examples/chain_client/exchange/20_MsgIncreasePositionMargin.py similarity index 96% rename from examples/chain_client/13_MsgIncreasePositionMargin.py rename to examples/chain_client/exchange/20_MsgIncreasePositionMargin.py index 775a41e5..276276e7 100644 --- a/examples/chain_client/13_MsgIncreasePositionMargin.py +++ b/examples/chain_client/exchange/20_MsgIncreasePositionMargin.py @@ -1,5 +1,6 @@ import asyncio import os +from decimal import Decimal import dotenv from grpc import RpcError @@ -34,12 +35,12 @@ async def main() -> None: market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" # prepare tx msg - msg = composer.MsgIncreasePositionMargin( + msg = composer.msg_increase_position_margin( sender=address.to_acc_bech32(), market_id=market_id, source_subaccount_id=subaccount_id, destination_subaccount_id=subaccount_id, - amount=2, + amount=Decimal(2), ) # build sim tx diff --git a/examples/chain_client/exchange/12_MsgRewardsOptOut.py b/examples/chain_client/exchange/21_MsgRewardsOptOut.py similarity index 97% rename from examples/chain_client/exchange/12_MsgRewardsOptOut.py rename to examples/chain_client/exchange/21_MsgRewardsOptOut.py index 8beaa1f4..2306b541 100644 --- a/examples/chain_client/exchange/12_MsgRewardsOptOut.py +++ b/examples/chain_client/exchange/21_MsgRewardsOptOut.py @@ -30,7 +30,7 @@ async def main() -> None: await client.fetch_account(address.to_acc_bech32()) # prepare tx msg - msg = composer.MsgRewardsOptOut(sender=address.to_acc_bech32()) + msg = composer.msg_rewards_opt_out(sender=address.to_acc_bech32()) # build sim tx tx = ( diff --git a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py b/examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py similarity index 96% rename from examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py rename to examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py index 0f39dcdb..b638b28a 100644 --- a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py +++ b/examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py @@ -1,5 +1,6 @@ import asyncio import os +from decimal import Decimal import dotenv from grpc import RpcError @@ -32,12 +33,12 @@ async def main() -> None: # prepare trade info market_id = "0xfafec40a7b93331c1fc89c23f66d11fbb48f38dfdd78f7f4fc4031fad90f6896" status = "Demolished" - settlement_price = 1 + settlement_price = Decimal(1) expiration_timestamp = 1685460582 settlement_timestamp = 1690730982 # prepare tx msg - msg = composer.MsgAdminUpdateBinaryOptionsMarket( + msg = composer.msg_admin_update_binary_options_market( sender=address.to_acc_bech32(), market_id=market_id, settlement_price=settlement_price, diff --git a/examples/chain_client/exchange/9_MsgWithdraw.py b/examples/chain_client/exchange/2_MsgWithdraw.py similarity index 95% rename from examples/chain_client/exchange/9_MsgWithdraw.py rename to examples/chain_client/exchange/2_MsgWithdraw.py index b198c0aa..1070d28c 100644 --- a/examples/chain_client/exchange/9_MsgWithdraw.py +++ b/examples/chain_client/exchange/2_MsgWithdraw.py @@ -31,7 +31,7 @@ async def main() -> None: subaccount_id = address.get_subaccount_id(index=0) # prepare tx msg - msg = composer.MsgWithdraw(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom="USDT") + msg = composer.msg_withdraw(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom="USDT") # build sim tx tx = ( diff --git a/examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py b/examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py new file mode 100644 index 00000000..90a177ec --- /dev/null +++ b/examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py @@ -0,0 +1,54 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + await client.initialize_tokens_from_chain_denoms() + composer = await client.composer() + await client.sync_timeout_height() + + message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( + network=network, + private_key=configured_private_key, + ) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + message = composer.msg_instant_spot_market_launch( + sender=address.to_acc_bech32(), + ticker="INJ/USDC", + base_denom="INJ", + quote_denom="USDC", + min_price_tick_size=Decimal("0.001"), + min_quantity_tick_size=Decimal("0.01"), + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py b/examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py new file mode 100644 index 00000000..b2b5dff4 --- /dev/null +++ b/examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py @@ -0,0 +1,61 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + await client.initialize_tokens_from_chain_denoms() + composer = await client.composer() + await client.sync_timeout_height() + + message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( + network=network, + private_key=configured_private_key, + ) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + message = composer.msg_instant_perpetual_market_launch( + sender=address.to_acc_bech32(), + ticker="INJ/USDC PERP", + quote_denom="USDC", + oracle_base="INJ", + oracle_quote="USDC", + oracle_scale_factor=6, + oracle_type="Band", + maker_fee_rate=Decimal("-0.0001"), + taker_fee_rate=Decimal("0.001"), + initial_margin_ratio=Decimal("0.33"), + maintenance_margin_ratio=Decimal("0.095"), + min_price_tick_size=Decimal("0.001"), + min_quantity_tick_size=Decimal("0.01"), + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py b/examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py new file mode 100644 index 00000000..d451fd15 --- /dev/null +++ b/examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py @@ -0,0 +1,62 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + await client.initialize_tokens_from_chain_denoms() + composer = await client.composer() + await client.sync_timeout_height() + + message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( + network=network, + private_key=configured_private_key, + ) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + message = composer.msg_instant_expiry_futures_market_launch( + sender=address.to_acc_bech32(), + ticker="INJ/USDC FUT", + quote_denom="USDC", + oracle_base="INJ", + oracle_quote="USDC", + oracle_scale_factor=6, + oracle_type="Band", + expiry=2000000000, + maker_fee_rate=Decimal("-0.0001"), + taker_fee_rate=Decimal("0.001"), + initial_margin_ratio=Decimal("0.33"), + maintenance_margin_ratio=Decimal("0.095"), + min_price_tick_size=Decimal("0.001"), + min_quantity_tick_size=Decimal("0.01"), + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py similarity index 94% rename from examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py rename to examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py index d3ca5f16..5b3b966a 100644 --- a/examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py +++ b/examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -37,15 +38,14 @@ async def main() -> None: cid = str(uuid.uuid4()) # prepare tx msg - msg = composer.MsgCreateSpotLimitOrder( + msg = composer.msg_create_spot_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=cid, ) diff --git a/examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py similarity index 94% rename from examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py rename to examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py index 5229632f..36ea27de 100644 --- a/examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py +++ b/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,14 +37,14 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateSpotMarketOrder( - sender=address.to_acc_bech32(), + msg = composer.msg_create_spot_market_order( market_id=market_id, + sender=address.to_acc_bech32(), subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=10.522, - quantity=0.01, - is_buy=True, + price=Decimal("10.522"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/exchange/5_MsgCancelSpotOrder.py b/examples/chain_client/exchange/8_MsgCancelSpotOrder.py similarity index 100% rename from examples/chain_client/exchange/5_MsgCancelSpotOrder.py rename to examples/chain_client/exchange/8_MsgCancelSpotOrder.py diff --git a/examples/chain_client/exchange/11_MsgBatchUpdateOrders.py b/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py similarity index 83% rename from examples/chain_client/exchange/11_MsgBatchUpdateOrders.py rename to examples/chain_client/exchange/9_MsgBatchUpdateOrders.py index 9efdc0a0..04e41058 100644 --- a/examples/chain_client/exchange/11_MsgBatchUpdateOrders.py +++ b/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -43,12 +44,12 @@ async def main() -> None: spot_market_id_cancel_2 = "0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0" derivative_orders_to_cancel = [ - composer.OrderData( + composer.order_data( market_id=derivative_market_id_cancel, subaccount_id=subaccount_id, order_hash="0x48690013c382d5dbaff9989db04629a16a5818d7524e027d517ccc89fd068103", ), - composer.OrderData( + composer.order_data( market_id=derivative_market_id_cancel_2, subaccount_id=subaccount_id, order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -56,12 +57,12 @@ async def main() -> None: ] spot_orders_to_cancel = [ - composer.OrderData( + composer.order_data( market_id=spot_market_id_cancel, subaccount_id=subaccount_id, cid="0e5c3ad5-2cc4-4a2a-bbe5-b12697739163", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id_cancel_2, subaccount_id=subaccount_id, order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", @@ -69,49 +70,49 @@ async def main() -> None: ] derivative_orders_to_create = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=derivative_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=25000, - quantity=0.1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(25000), + quantity=Decimal(0.1), + margin=composer.calculate_margin( + quantity=Decimal(0.1), price=Decimal(25000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.DerivativeOrder( + composer.derivative_order( market_id=derivative_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=50000, - quantity=0.01, - leverage=1, - is_buy=False, - is_po=False, + price=Decimal(50000), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ), ] spot_orders_to_create = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=3, - quantity=55, - is_buy=True, - is_po=False, + price=Decimal("3"), + quantity=Decimal("55"), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=300, - quantity=55, - is_buy=False, - is_po=False, + price=Decimal("300"), + quantity=Decimal("55"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] diff --git a/examples/chain_client/41_MsgCreateInsuranceFund.py b/examples/chain_client/insurance/1_MsgCreateInsuranceFund.py similarity index 100% rename from examples/chain_client/41_MsgCreateInsuranceFund.py rename to examples/chain_client/insurance/1_MsgCreateInsuranceFund.py diff --git a/examples/chain_client/42_MsgUnderwrite.py b/examples/chain_client/insurance/2_MsgUnderwrite.py similarity index 100% rename from examples/chain_client/42_MsgUnderwrite.py rename to examples/chain_client/insurance/2_MsgUnderwrite.py diff --git a/examples/chain_client/43_MsgRequestRedemption.py b/examples/chain_client/insurance/3_MsgRequestRedemption.py similarity index 100% rename from examples/chain_client/43_MsgRequestRedemption.py rename to examples/chain_client/insurance/3_MsgRequestRedemption.py diff --git a/examples/chain_client/23_MsgRelayPriceFeedPrice.py b/examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py similarity index 100% rename from examples/chain_client/23_MsgRelayPriceFeedPrice.py rename to examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py diff --git a/examples/chain_client/36_MsgRelayProviderPrices.py b/examples/chain_client/oracle/2_MsgRelayProviderPrices.py similarity index 100% rename from examples/chain_client/36_MsgRelayProviderPrices.py rename to examples/chain_client/oracle/2_MsgRelayProviderPrices.py diff --git a/examples/chain_client/22_MsgSendToEth.py b/examples/chain_client/peggy/1_MsgSendToEth.py similarity index 100% rename from examples/chain_client/22_MsgSendToEth.py rename to examples/chain_client/peggy/1_MsgSendToEth.py diff --git a/examples/chain_client/25_MsgDelegate.py b/examples/chain_client/staking/1_MsgDelegate.py similarity index 100% rename from examples/chain_client/25_MsgDelegate.py rename to examples/chain_client/staking/1_MsgDelegate.py diff --git a/examples/chain_client/71_CreateDenom.py b/examples/chain_client/tokenfactory/1_CreateDenom.py similarity index 100% rename from examples/chain_client/71_CreateDenom.py rename to examples/chain_client/tokenfactory/1_CreateDenom.py diff --git a/examples/chain_client/72_MsgMint.py b/examples/chain_client/tokenfactory/2_MsgMint.py similarity index 100% rename from examples/chain_client/72_MsgMint.py rename to examples/chain_client/tokenfactory/2_MsgMint.py diff --git a/examples/chain_client/73_MsgBurn.py b/examples/chain_client/tokenfactory/3_MsgBurn.py similarity index 100% rename from examples/chain_client/73_MsgBurn.py rename to examples/chain_client/tokenfactory/3_MsgBurn.py diff --git a/examples/chain_client/75_MsgChangeAdmin.py b/examples/chain_client/tokenfactory/4_MsgChangeAdmin.py similarity index 100% rename from examples/chain_client/75_MsgChangeAdmin.py rename to examples/chain_client/tokenfactory/4_MsgChangeAdmin.py diff --git a/examples/chain_client/74_MsgSetDenomMetadata.py b/examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py similarity index 100% rename from examples/chain_client/74_MsgSetDenomMetadata.py rename to examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py diff --git a/examples/chain_client/68_DenomAuthorityMetadata.py b/examples/chain_client/tokenfactory/query/1_DenomAuthorityMetadata.py similarity index 100% rename from examples/chain_client/68_DenomAuthorityMetadata.py rename to examples/chain_client/tokenfactory/query/1_DenomAuthorityMetadata.py diff --git a/examples/chain_client/69_DenomsFromCreator.py b/examples/chain_client/tokenfactory/query/2_DenomsFromCreator.py similarity index 100% rename from examples/chain_client/69_DenomsFromCreator.py rename to examples/chain_client/tokenfactory/query/2_DenomsFromCreator.py diff --git a/examples/chain_client/70_TokenfactoryModuleState.py b/examples/chain_client/tokenfactory/query/3_TokenfactoryModuleState.py similarity index 100% rename from examples/chain_client/70_TokenfactoryModuleState.py rename to examples/chain_client/tokenfactory/query/3_TokenfactoryModuleState.py diff --git a/examples/chain_client/37_GetTx.py b/examples/chain_client/tx/query/1_GetTx.py similarity index 100% rename from examples/chain_client/37_GetTx.py rename to examples/chain_client/tx/query/1_GetTx.py diff --git a/examples/chain_client/40_MsgExecuteContract.py b/examples/chain_client/wasm/1_MsgExecuteContract.py similarity index 100% rename from examples/chain_client/40_MsgExecuteContract.py rename to examples/chain_client/wasm/1_MsgExecuteContract.py diff --git a/examples/chain_client/67_ContractsByCreator.py b/examples/chain_client/wasm/query/10_ContractsByCreator.py similarity index 100% rename from examples/chain_client/67_ContractsByCreator.py rename to examples/chain_client/wasm/query/10_ContractsByCreator.py diff --git a/examples/chain_client/58_ContractInfo.py b/examples/chain_client/wasm/query/1_ContractInfo.py similarity index 100% rename from examples/chain_client/58_ContractInfo.py rename to examples/chain_client/wasm/query/1_ContractInfo.py diff --git a/examples/chain_client/59_ContractHistory.py b/examples/chain_client/wasm/query/2_ContractHistory.py similarity index 100% rename from examples/chain_client/59_ContractHistory.py rename to examples/chain_client/wasm/query/2_ContractHistory.py diff --git a/examples/chain_client/60_ContractsByCode.py b/examples/chain_client/wasm/query/3_ContractsByCode.py similarity index 100% rename from examples/chain_client/60_ContractsByCode.py rename to examples/chain_client/wasm/query/3_ContractsByCode.py diff --git a/examples/chain_client/61_AllContractsState.py b/examples/chain_client/wasm/query/4_AllContractsState.py similarity index 100% rename from examples/chain_client/61_AllContractsState.py rename to examples/chain_client/wasm/query/4_AllContractsState.py diff --git a/examples/chain_client/62_RawContractState.py b/examples/chain_client/wasm/query/5_RawContractState.py similarity index 100% rename from examples/chain_client/62_RawContractState.py rename to examples/chain_client/wasm/query/5_RawContractState.py diff --git a/examples/chain_client/63_SmartContractState.py b/examples/chain_client/wasm/query/6_SmartContractState.py similarity index 100% rename from examples/chain_client/63_SmartContractState.py rename to examples/chain_client/wasm/query/6_SmartContractState.py diff --git a/examples/chain_client/64_SmartContractCode.py b/examples/chain_client/wasm/query/7_SmartContractCode.py similarity index 100% rename from examples/chain_client/64_SmartContractCode.py rename to examples/chain_client/wasm/query/7_SmartContractCode.py diff --git a/examples/chain_client/65_SmartContractCodes.py b/examples/chain_client/wasm/query/8_SmartContractCodes.py similarity index 100% rename from examples/chain_client/65_SmartContractCodes.py rename to examples/chain_client/wasm/query/8_SmartContractCodes.py diff --git a/examples/chain_client/66_SmartContractPinnedCodes.py b/examples/chain_client/wasm/query/9_SmartContractPinnedCodes.py similarity index 100% rename from examples/chain_client/66_SmartContractPinnedCodes.py rename to examples/chain_client/wasm/query/9_SmartContractPinnedCodes.py diff --git a/pyinjective/composer.py b/pyinjective/composer.py index df353d6b..9a0807c9 100644 --- a/pyinjective/composer.py +++ b/pyinjective/composer.py @@ -13,7 +13,7 @@ from pyinjective.core.token import Token from pyinjective.proto.cosmos.authz.v1beta1 import authz_pb2 as cosmos_authz_pb, tx_pb2 as cosmos_authz_tx_pb from pyinjective.proto.cosmos.bank.v1beta1 import bank_pb2 as bank_pb, tx_pb2 as cosmos_bank_tx_pb -from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as cosmos_dot_base_dot_v1beta1_dot_coin__pb2 +from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as base_coin_pb from pyinjective.proto.cosmos.distribution.v1beta1 import ( distribution_pb2 as cosmos_distribution_pb2, tx_pb2 as cosmos_distribution_tx_pb, @@ -25,15 +25,19 @@ from pyinjective.proto.injective.auction.v1beta1 import tx_pb2 as injective_auction_tx_pb from pyinjective.proto.injective.exchange.v1beta1 import ( authz_pb2 as injective_authz_pb, - exchange_pb2 as injective_dot_exchange_dot_v1beta1_dot_exchange__pb2, + exchange_pb2 as injective_exchange_pb, tx_pb2 as injective_exchange_tx_pb, ) from pyinjective.proto.injective.insurance.v1beta1 import tx_pb2 as injective_insurance_tx_pb -from pyinjective.proto.injective.oracle.v1beta1 import tx_pb2 as injective_oracle_tx_pb +from pyinjective.proto.injective.oracle.v1beta1 import ( + oracle_pb2 as injective_oracle_pb, + tx_pb2 as injective_oracle_tx_pb, +) from pyinjective.proto.injective.peggy.v1 import msgs_pb2 as injective_peggy_tx_pb from pyinjective.proto.injective.stream.v1beta1 import query_pb2 as chain_stream_query from pyinjective.proto.injective.tokenfactory.v1beta1 import tx_pb2 as token_factory_tx_pb from pyinjective.proto.injective.wasmx.v1 import tx_pb2 as wasmx_tx_pb +from pyinjective.utils.denom import Denom REQUEST_TO_RESPONSE_TYPE_MAP = { "MsgCreateSpotLimitOrder": injective_exchange_tx_pb.MsgCreateSpotLimitOrderResponse, @@ -137,14 +141,14 @@ def Coin(self, amount: int, denom: str): This method is deprecated and will be removed soon. Please use `coin` instead """ warn("This method is deprecated. Use coin instead", DeprecationWarning, stacklevel=2) - return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=str(amount), denom=denom) + return base_coin_pb.Coin(amount=str(amount), denom=denom) def coin(self, amount: int, denom: str): """ This method create an instance of Coin gRPC type, considering the amount is already expressed in chain format """ formatted_amount_string = str(int(amount)) - return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=formatted_amount_string, denom=denom) + return base_coin_pb.Coin(amount=formatted_amount_string, denom=denom) def create_coin_amount(self, amount: Decimal, token_name: str): """ @@ -154,35 +158,38 @@ def create_coin_amount(self, amount: Decimal, token_name: str): chain_amount = token.chain_formatted_value(human_readable_value=amount) return self.coin(amount=int(chain_amount), denom=token.denom) - def get_order_mask(self, **kwargs): - order_mask = 0 - - if kwargs.get("is_conditional"): - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.CONDITIONAL - else: - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.REGULAR - - if kwargs.get("order_direction") == "buy": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.DIRECTION_BUY_OR_HIGHER - - elif kwargs.get("order_direction") == "sell": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.DIRECTION_SELL_OR_LOWER - - if kwargs.get("order_type") == "market": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.TYPE_MARKET - - elif kwargs.get("order_type") == "limit": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.TYPE_LIMIT - - if order_mask == 0: - order_mask = 1 - - return order_mask - def OrderData( self, market_id: str, subaccount_id: str, order_hash: Optional[str] = None, cid: Optional[str] = None, **kwargs ): - order_mask = self.get_order_mask(**kwargs) + """ + This method is deprecated and will be removed soon. Please use `order_data` instead + """ + warn("This method is deprecated. Use order_data instead", DeprecationWarning, stacklevel=2) + + is_conditional = kwargs.get("is_conditional", False) + is_buy = kwargs.get("order_direction", "buy") == "buy" + is_market_order = kwargs.get("order_type", "limit") == "market" + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) + + return injective_exchange_tx_pb.OrderData( + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + order_mask=order_mask, + cid=cid, + ) + + def order_data( + self, + market_id: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + is_conditional: Optional[bool] = False, + is_buy: Optional[bool] = False, + is_market_order: Optional[bool] = False, + ) -> injective_exchange_tx_pb.OrderData: + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) return injective_exchange_tx_pb.OrderData( market_id=market_id, @@ -202,6 +209,11 @@ def SpotOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `spot_order` instead + """ + warn("This method is deprecated. Use spot_order instead", DeprecationWarning, stacklevel=2) + market = self.spot_markets[market_id] # prepare values @@ -210,20 +222,20 @@ def SpotOrder( trigger_price = market.price_to_chain_format(human_readable_value=Decimal(0)) if kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY + order_type = injective_exchange_pb.OrderType.BUY elif not kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL + order_type = injective_exchange_pb.OrderType.SELL elif kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY_PO + order_type = injective_exchange_pb.OrderType.BUY_PO elif not kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL_PO + order_type = injective_exchange_pb.OrderType.SELL_PO - return injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.SpotOrder( + return injective_exchange_pb.SpotOrder( market_id=market_id, - order_info=injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderInfo( + order_info=injective_exchange_pb.OrderInfo( subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=str(int(price)), @@ -234,6 +246,50 @@ def SpotOrder( trigger_price=str(int(trigger_price)), ) + def spot_order( + self, + market_id: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_pb.SpotOrder: + market = self.spot_markets[market_id] + + chain_quantity = f"{market.quantity_to_chain_format(human_readable_value=quantity).normalize():f}" + chain_price = f"{market.price_to_chain_format(human_readable_value=price).normalize():f}" + + trigger_price = trigger_price or Decimal(0) + chain_trigger_price = f"{market.price_to_chain_format(human_readable_value=trigger_price).normalize():f}" + + chain_order_type = injective_exchange_pb.OrderType.Value(order_type) + + return injective_exchange_pb.SpotOrder( + market_id=market_id, + order_info=injective_exchange_pb.OrderInfo( + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=chain_price, + quantity=chain_quantity, + cid=cid, + ), + order_type=chain_order_type, + trigger_price=chain_trigger_price, + ) + + def calculate_margin( + self, quantity: Decimal, price: Decimal, leverage: Decimal, is_reduce_only: bool = False + ) -> Decimal: + if is_reduce_only: + margin = Decimal(0) + else: + margin = quantity * price / leverage + + return margin + def DerivativeOrder( self, market_id: str, @@ -245,6 +301,10 @@ def DerivativeOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `derivative_order` instead + """ + warn("This method is deprecated. Use derivative_order instead", DeprecationWarning, stacklevel=2) market = self.derivative_markets[market_id] if kwargs.get("is_reduce_only", False): @@ -262,32 +322,32 @@ def DerivativeOrder( trigger_price = market.price_to_chain_format(human_readable_value=Decimal(str(trigger_price))) if kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY + order_type = injective_exchange_pb.OrderType.BUY elif not kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL + order_type = injective_exchange_pb.OrderType.SELL elif kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY_PO + order_type = injective_exchange_pb.OrderType.BUY_PO elif not kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL_PO + order_type = injective_exchange_pb.OrderType.SELL_PO elif kwargs.get("stop_buy"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.STOP_BUY + order_type = injective_exchange_pb.OrderType.STOP_BUY elif kwargs.get("stop_sell"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.STOP_SEll + order_type = injective_exchange_pb.OrderType.STOP_SEll elif kwargs.get("take_buy"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.TAKE_BUY + order_type = injective_exchange_pb.OrderType.TAKE_BUY elif kwargs.get("take_sell"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.TAKE_SELL + order_type = injective_exchange_pb.OrderType.TAKE_SELL - return injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.DerivativeOrder( + return injective_exchange_pb.DerivativeOrder( market_id=market_id, - order_info=injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderInfo( + order_info=injective_exchange_pb.OrderInfo( subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=str(int(price)), @@ -299,60 +359,121 @@ def DerivativeOrder( trigger_price=str(int(trigger_price)), ) - def BinaryOptionsOrder( + def derivative_order( self, market_id: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, cid: Optional[str] = None, - **kwargs, - ): - market = self.binary_option_markets[market_id] - denom = kwargs.get("denom", None) + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_pb.DerivativeOrder: + market = self.derivative_markets[market_id] - if kwargs.get("is_reduce_only", False): - margin = 0 - else: - margin = market.calculate_margin_in_chain_format( - human_readable_quantity=Decimal(str(quantity)), - human_readable_price=Decimal(str(price)), - is_buy=kwargs["is_buy"], - special_denom=denom, - ) + chain_quantity = market.quantity_to_chain_format(human_readable_value=quantity) + chain_price = market.price_to_chain_format(human_readable_value=price) + chain_margin = market.margin_to_chain_format(human_readable_value=margin) - # prepare values - price = market.price_to_chain_format(human_readable_value=Decimal(str(price)), special_denom=denom) - trigger_price = market.price_to_chain_format(human_readable_value=Decimal(str(0)), special_denom=denom) - quantity = market.quantity_to_chain_format(human_readable_value=Decimal(str(quantity)), special_denom=denom) + trigger_price = trigger_price or Decimal(0) + chain_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price) - if kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY + return self._basic_derivative_order( + market_id=market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + chain_price=chain_price, + chain_quantity=chain_quantity, + chain_margin=chain_margin, + order_type=order_type, + cid=cid, + chain_trigger_price=chain_trigger_price, + ) - elif not kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL + def binary_options_order( + self, + market_id: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + denom: Optional[Denom] = None, + ) -> injective_exchange_pb.DerivativeOrder: + market = self.binary_option_markets[market_id] - elif kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY_PO + chain_quantity = market.quantity_to_chain_format(human_readable_value=quantity, special_denom=denom) + chain_price = market.price_to_chain_format(human_readable_value=price, special_denom=denom) + chain_margin = market.margin_to_chain_format(human_readable_value=margin, special_denom=denom) - elif not kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL_PO + trigger_price = trigger_price or Decimal(0) + chain_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price, special_denom=denom) - return injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.DerivativeOrder( - market_id=market_id, - order_info=injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderInfo( - subaccount_id=subaccount_id, - fee_recipient=fee_recipient, - price=str(int(price)), - quantity=str(int(quantity)), - cid=cid, - ), - margin=str(int(margin)), + return self._basic_derivative_order( + market_id=market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + chain_price=chain_price, + chain_quantity=chain_quantity, + chain_margin=chain_margin, order_type=order_type, - trigger_price=str(int(trigger_price)), + cid=cid, + chain_trigger_price=chain_trigger_price, + ) + + # region Auction module + def MsgBid(self, sender: str, bid_amount: float, round: float): + be_amount = Decimal(str(bid_amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_auction_tx_pb.MsgBid( + sender=sender, + round=round, + bid_amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), + ) + + # endregion + + # region Authz module + def MsgGrantGeneric(self, granter: str, grantee: str, msg_type: str, expire_in: int): + auth = cosmos_authz_pb.GenericAuthorization(msg=msg_type) + any_auth = any_pb2.Any() + any_auth.Pack(auth, type_url_prefix="") + + grant = cosmos_authz_pb.Grant( + authorization=any_auth, + expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), + ) + + return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + + def MsgExec(self, grantee: str, msgs: List): + any_msgs: List[any_pb2.Any] = [] + for msg in msgs: + any_msg = any_pb2.Any() + any_msg.Pack(msg, type_url_prefix="") + any_msgs.append(any_msg) + + return cosmos_authz_tx_pb.MsgExec(grantee=grantee, msgs=any_msgs) + + def MsgRevoke(self, granter: str, grantee: str, msg_type: str): + return cosmos_authz_tx_pb.MsgRevoke(granter=granter, grantee=grantee, msg_type_url=msg_type) + + def msg_execute_contract_compat(self, sender: str, contract: str, msg: str, funds: str): + return wasmx_tx_pb.MsgExecuteContractCompat( + sender=sender, + contract=contract, + msg=msg, + funds=funds, ) + # endregion + + # region Bank module def MsgSend(self, from_address: str, to_address: str, amount: float, denom: str): coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) @@ -362,16 +483,14 @@ def MsgSend(self, from_address: str, to_address: str, amount: float, denom: str) amount=[coin], ) - def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): - return wasm_tx_pb.MsgExecuteContract( - sender=sender, - contract=contract, - msg=bytes(msg, "utf-8"), - funds=kwargs.get("funds") # funds is a list of cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin. - # The coins in the list must be sorted in alphabetical order by denoms. - ) + # endregion + # region Chain Exchange module def MsgDeposit(self, sender: str, subaccount_id: str, amount: float, denom: str): + """ + This method is deprecated and will be removed soon. Please use `msg_deposit` instead + """ + warn("This method is deprecated. Use msg_deposit instead", DeprecationWarning, stacklevel=2) coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgDeposit( @@ -380,6 +499,153 @@ def MsgDeposit(self, sender: str, subaccount_id: str, amount: float, denom: str) amount=coin, ) + def msg_deposit(self, sender: str, subaccount_id: str, amount: Decimal, denom: str): + coin = self.create_coin_amount(amount=amount, token_name=denom) + + return injective_exchange_tx_pb.MsgDeposit( + sender=sender, + subaccount_id=subaccount_id, + amount=coin, + ) + + def MsgWithdraw(self, sender: str, subaccount_id: str, amount: float, denom: str): + """ + This method is deprecated and will be removed soon. Please use `msg_withdraw` instead + """ + warn("This method is deprecated. Use msg_withdraw instead", DeprecationWarning, stacklevel=2) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + + return injective_exchange_tx_pb.MsgWithdraw( + sender=sender, + subaccount_id=subaccount_id, + amount=be_amount, + ) + + def msg_withdraw(self, sender: str, subaccount_id: str, amount: Decimal, denom: str): + be_amount = self.create_coin_amount(amount=amount, token_name=denom) + + return injective_exchange_tx_pb.MsgWithdraw( + sender=sender, + subaccount_id=subaccount_id, + amount=be_amount, + ) + + def msg_instant_spot_market_launch( + self, + sender: str, + ticker: str, + base_denom: str, + quote_denom: str, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantSpotMarketLaunch: + base_token = self.tokens[base_denom] + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals - base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal( + f"1e{base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + + return injective_exchange_tx_pb.MsgInstantSpotMarketLaunch( + sender=sender, + ticker=ticker, + base_denom=base_token.denom, + quote_denom=quote_token.denom, + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", + ) + + def msg_instant_perpetual_market_launch( + self, + sender: str, + ticker: str, + quote_denom: str, + oracle_base: str, + oracle_quote: str, + oracle_scale_factor: int, + oracle_type: str, + maker_fee_rate: Decimal, + taker_fee_rate: Decimal, + initial_margin_ratio: Decimal, + maintenance_margin_ratio: Decimal, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch: + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch( + sender=sender, + ticker=ticker, + quote_denom=quote_token.denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=injective_oracle_pb.OracleType.Value(oracle_type), + maker_fee_rate=f"{chain_maker_fee_rate.normalize():f}", + taker_fee_rate=f"{chain_taker_fee_rate.normalize():f}", + initial_margin_ratio=f"{chain_initial_margin_ratio.normalize():f}", + maintenance_margin_ratio=f"{chain_maintenance_margin_ratio.normalize():f}", + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", + ) + + def msg_instant_expiry_futures_market_launch( + self, + sender: str, + ticker: str, + quote_denom: str, + oracle_base: str, + oracle_quote: str, + oracle_scale_factor: int, + oracle_type: str, + expiry: int, + maker_fee_rate: Decimal, + taker_fee_rate: Decimal, + initial_margin_ratio: Decimal, + maintenance_margin_ratio: Decimal, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch: + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_exchange_tx_pb.MsgInstantExpiryFuturesMarketLaunch( + sender=sender, + ticker=ticker, + quote_denom=quote_token.denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=injective_oracle_pb.OracleType.Value(oracle_type), + expiry=expiry, + maker_fee_rate=f"{chain_maker_fee_rate.normalize():f}", + taker_fee_rate=f"{chain_taker_fee_rate.normalize():f}", + initial_margin_ratio=f"{chain_initial_margin_ratio.normalize():f}", + maintenance_margin_ratio=f"{chain_maintenance_margin_ratio.normalize():f}", + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", + ) + def MsgCreateSpotLimitOrder( self, market_id: str, @@ -391,52 +657,151 @@ def MsgCreateSpotLimitOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `msg_create_spot_limit_order` instead + """ + warn("This method is deprecated. Use msg_create_spot_limit_order instead", DeprecationWarning, stacklevel=2) + + order_type_name = "BUY" + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + return injective_exchange_tx_pb.MsgCreateSpotLimitOrder( sender=sender, - order=self.SpotOrder( + order=self.spot_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=price, - quantity=quantity, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + order_type=order_type_name, cid=cid, - **kwargs, ), ) - def MsgCreateSpotMarketOrder( + def msg_create_spot_limit_order( self, market_id: str, sender: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, - is_buy: bool, + price: Decimal, + quantity: Decimal, + order_type: str, cid: Optional[str] = None, - ): - return injective_exchange_tx_pb.MsgCreateSpotMarketOrder( + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateSpotLimitOrder: + return injective_exchange_tx_pb.MsgCreateSpotLimitOrder( sender=sender, - order=self.SpotOrder( + order=self.spot_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=price, quantity=quantity, - is_buy=is_buy, + order_type=order_type, cid=cid, + trigger_price=trigger_price, ), ) - def MsgCancelSpotOrder( + def MsgBatchCreateSpotLimitOrders(self, sender: str, orders: List): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_create_spot_limit_orders` instead + """ + warn( + "This method is deprecated. Use msg_batch_create_spot_limit_orders instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders(sender=sender, orders=orders) + + def msg_batch_create_spot_limit_orders( + self, sender: str, orders: List[injective_exchange_pb.SpotOrder] + ) -> injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders: + return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders(sender=sender, orders=orders) + + def MsgCreateSpotMarketOrder( self, market_id: str, sender: str, subaccount_id: str, - order_hash: Optional[str] = None, + fee_recipient: str, + price: float, + quantity: float, + is_buy: bool, cid: Optional[str] = None, ): - return injective_exchange_tx_pb.MsgCancelSpotOrder( + """ + This method is deprecated and will be removed soon. Please use `msg_create_spot_market_order` instead + """ + warn("This method is deprecated. Use msg_create_spot_market_order instead", DeprecationWarning, stacklevel=2) + + order_type_name = "BUY" + if not is_buy: + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + return injective_exchange_tx_pb.MsgCreateSpotMarketOrder( + sender=sender, + order=self.spot_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + order_type=order_type_name, + cid=cid, + ), + ) + + def msg_create_spot_market_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateSpotMarketOrder: + return injective_exchange_tx_pb.MsgCreateSpotMarketOrder( + sender=sender, + order=self.spot_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ), + ) + + def MsgCancelSpotOrder( + self, + market_id: str, + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_cancel_spot_order` instead + """ + warn("This method is deprecated. Use msg_cancel_spot_order instead", DeprecationWarning, stacklevel=2) + return injective_exchange_tx_pb.MsgCancelSpotOrder( sender=sender, market_id=market_id, subaccount_id=subaccount_id, @@ -444,14 +809,111 @@ def MsgCancelSpotOrder( cid=cid, ) - def MsgBatchCreateSpotLimitOrders(self, sender: str, orders: List): - return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders(sender=sender, orders=orders) + def msg_cancel_spot_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + ) -> injective_exchange_tx_pb.MsgCancelSpotOrder: + return injective_exchange_tx_pb.MsgCancelSpotOrder( + sender=sender, + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + ) def MsgBatchCancelSpotOrders(self, sender: str, data: List): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_cancel_spot_orders` instead + """ + warn("This method is deprecated. Use msg_batch_cancel_spot_orders instead", DeprecationWarning, stacklevel=2) return injective_exchange_tx_pb.MsgBatchCancelSpotOrders(sender=sender, data=data) - def MsgRewardsOptOut(self, sender: str): - return injective_exchange_tx_pb.MsgRewardsOptOut(sender=sender) + def msg_batch_cancel_spot_orders( + self, sender: str, orders_data: List[injective_exchange_tx_pb.OrderData] + ) -> injective_exchange_tx_pb.MsgBatchCancelSpotOrders: + return injective_exchange_tx_pb.MsgBatchCancelSpotOrders(sender=sender, data=orders_data) + + def MsgBatchUpdateOrders(self, sender: str, **kwargs): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_update_orders` instead + """ + warn("This method is deprecated. Use msg_batch_update_orders instead", DeprecationWarning, stacklevel=2) + return injective_exchange_tx_pb.MsgBatchUpdateOrders( + sender=sender, + subaccount_id=kwargs.get("subaccount_id"), + spot_market_ids_to_cancel_all=kwargs.get("spot_market_ids_to_cancel_all"), + derivative_market_ids_to_cancel_all=kwargs.get("derivative_market_ids_to_cancel_all"), + spot_orders_to_cancel=kwargs.get("spot_orders_to_cancel"), + derivative_orders_to_cancel=kwargs.get("derivative_orders_to_cancel"), + spot_orders_to_create=kwargs.get("spot_orders_to_create"), + derivative_orders_to_create=kwargs.get("derivative_orders_to_create"), + binary_options_orders_to_cancel=kwargs.get("binary_options_orders_to_cancel"), + binary_options_market_ids_to_cancel_all=kwargs.get("binary_options_market_ids_to_cancel_all"), + binary_options_orders_to_create=kwargs.get("binary_options_orders_to_create"), + ) + + def msg_batch_update_orders( + self, + sender: str, + subaccount_id: Optional[str] = None, + spot_market_ids_to_cancel_all: Optional[List[str]] = None, + derivative_market_ids_to_cancel_all: Optional[List[str]] = None, + spot_orders_to_cancel: Optional[List[injective_exchange_tx_pb.OrderData]] = None, + derivative_orders_to_cancel: Optional[List[injective_exchange_tx_pb.OrderData]] = None, + spot_orders_to_create: Optional[List[injective_exchange_pb.SpotOrder]] = None, + derivative_orders_to_create: Optional[List[injective_exchange_pb.DerivativeOrder]] = None, + binary_options_orders_to_cancel: Optional[List[injective_exchange_tx_pb.OrderData]] = None, + binary_options_market_ids_to_cancel_all: Optional[List[str]] = None, + binary_options_orders_to_create: Optional[List[injective_exchange_pb.DerivativeOrder]] = None, + ) -> injective_exchange_tx_pb.MsgBatchUpdateOrders: + return injective_exchange_tx_pb.MsgBatchUpdateOrders( + sender=sender, + subaccount_id=subaccount_id, + spot_market_ids_to_cancel_all=spot_market_ids_to_cancel_all, + derivative_market_ids_to_cancel_all=derivative_market_ids_to_cancel_all, + spot_orders_to_cancel=spot_orders_to_cancel, + derivative_orders_to_cancel=derivative_orders_to_cancel, + spot_orders_to_create=spot_orders_to_create, + derivative_orders_to_create=derivative_orders_to_create, + binary_options_orders_to_cancel=binary_options_orders_to_cancel, + binary_options_market_ids_to_cancel_all=binary_options_market_ids_to_cancel_all, + binary_options_orders_to_create=binary_options_orders_to_create, + ) + + def MsgPrivilegedExecuteContract( + self, sender: str, contract: str, msg: str, **kwargs + ) -> injective_exchange_tx_pb.MsgPrivilegedExecuteContract: + """ + This method is deprecated and will be removed soon. Please use `msg_privileged_execute_contract` instead + """ + warn("This method is deprecated. Use msg_privileged_execute_contract instead", DeprecationWarning, stacklevel=2) + + return injective_exchange_tx_pb.MsgPrivilegedExecuteContract( + sender=sender, + contract_address=contract, + data=msg, + funds=kwargs.get("funds") # funds is a string of Coin strings, comma separated, + # e.g. 100000inj,20000000000usdt + ) + + def msg_privileged_execute_contract( + self, + sender: str, + contract_address: str, + data: str, + funds: Optional[str] = None, + ) -> injective_exchange_tx_pb.MsgPrivilegedExecuteContract: + # funds is a string of Coin strings, comma separated, e.g. 100000inj,20000000000usdt + return injective_exchange_tx_pb.MsgPrivilegedExecuteContract( + sender=sender, + contract_address=contract_address, + data=data, + funds=funds, + ) def MsgCreateDerivativeLimitOrder( self, @@ -464,46 +926,105 @@ def MsgCreateDerivativeLimitOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `msg_create_derivative_limit_order` instead + """ + warn( + "This method is deprecated. Use msg_create_derivative_limit_order instead", DeprecationWarning, stacklevel=2 + ) + + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) / Decimal(str(kwargs["leverage"])) + + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + return injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder( sender=sender, - order=self.DerivativeOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=price, - quantity=quantity, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, ), ) - def MsgCreateDerivativeMarketOrder( + def msg_create_derivative_limit_order( self, market_id: str, sender: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, - is_buy: bool, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, cid: Optional[str] = None, - **kwargs, - ): - return injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder( + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder: + return injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder( sender=sender, - order=self.DerivativeOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=price, quantity=quantity, - is_buy=is_buy, + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=trigger_price, ), ) - def MsgCreateBinaryOptionsLimitOrder( + def MsgBatchCreateDerivativeLimitOrders(self, sender: str, orders: List): + """ + This method is deprecated and will be removed soon. + Please use `msg_batch_create_derivative_limit_orders` instead + """ + warn( + "This method is deprecated. Use msg_batch_create_derivative_limit_orders instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders(sender=sender, orders=orders) + + def msg_batch_create_derivative_limit_orders( + self, + sender: str, + orders: List[injective_exchange_pb.DerivativeOrder], + ) -> injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders: + return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders(sender=sender, orders=orders) + + def MsgCreateDerivativeMarketOrder( self, market_id: str, sender: str, @@ -514,95 +1035,156 @@ def MsgCreateBinaryOptionsLimitOrder( cid: Optional[str] = None, **kwargs, ): - return injective_exchange_tx_pb.MsgCreateBinaryOptionsLimitOrder( + """ + This method is deprecated and will be removed soon. Please use `msg_create_derivative_market_order` instead + """ + warn( + "This method is deprecated. Use msg_create_derivative_market_order instead", + DeprecationWarning, + stacklevel=2, + ) + + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) / Decimal(str(kwargs["leverage"])) + + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + + return injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder( sender=sender, - order=self.BinaryOptionsOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=price, - quantity=quantity, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, ), ) - def MsgCreateBinaryOptionsMarketOrder( + def msg_create_derivative_market_order( self, market_id: str, sender: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, cid: Optional[str] = None, - **kwargs, - ): - return injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder( + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder: + return injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder( sender=sender, - order=self.BinaryOptionsOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=price, quantity=quantity, + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=trigger_price, ), ) - def MsgCancelBinaryOptionsOrder( + def MsgCancelDerivativeOrder( self, - sender: str, market_id: str, + sender: str, subaccount_id: str, order_hash: Optional[str] = None, cid: Optional[str] = None, + **kwargs, ): - return injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder( + """ + This method is deprecated and will be removed soon. Please use `msg_cancel_derivative_order` instead + """ + warn( + "This method is deprecated. Use msg_cancel_derivative_order instead", + DeprecationWarning, + stacklevel=2, + ) + + is_conditional = kwargs.get("is_conditional", False) + is_buy = kwargs.get("order_direction", "buy") == "buy" + is_market_order = kwargs.get("order_type", "limit") == "market" + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) + + return injective_exchange_tx_pb.MsgCancelDerivativeOrder( sender=sender, market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash, + order_mask=order_mask, cid=cid, ) - def MsgAdminUpdateBinaryOptionsMarket( + def msg_cancel_derivative_order( self, - sender: str, market_id: str, - status: str, - **kwargs, - ): - price_to_bytes = None - - if kwargs.get("settlement_price") is not None: - scale_price = Decimal((kwargs.get("settlement_price") * pow(10, 18))) - price_to_bytes = bytes(str(scale_price), "utf-8") - - else: - price_to_bytes = "" + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + is_conditional: Optional[bool] = False, + is_buy: Optional[bool] = False, + is_market_order: Optional[bool] = False, + ) -> injective_exchange_tx_pb.MsgCancelDerivativeOrder: + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) - return injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket( + return injective_exchange_tx_pb.MsgCancelDerivativeOrder( sender=sender, market_id=market_id, - settlement_price=price_to_bytes, - expiration_timestamp=kwargs.get("expiration_timestamp"), - settlement_timestamp=kwargs.get("settlement_timestamp"), - status=status, + subaccount_id=subaccount_id, + order_hash=order_hash, + order_mask=order_mask, + cid=cid, ) - def MsgRelayProviderPrices(self, sender: str, provider: str, symbols: list, prices: list): - oracle_prices = [] - - for price in prices: - scale_price = Decimal((price) * pow(10, 18)) - price_to_bytes = bytes(str(scale_price), "utf-8") - oracle_prices.append(price_to_bytes) - - return injective_oracle_tx_pb.MsgRelayProviderPrices( - sender=sender, provider=provider, symbols=symbols, prices=oracle_prices + def MsgBatchCancelDerivativeOrders(self, sender: str, data: List): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_cancel_derivative_orders` instead + """ + warn( + "This method is deprecated. Use msg_batch_cancel_derivative_orders instead", + DeprecationWarning, + stacklevel=2, ) + return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders(sender=sender, data=data) + + def msg_batch_cancel_derivative_orders( + self, sender: str, orders_data: List[injective_exchange_tx_pb.OrderData] + ) -> injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders: + return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders(sender=sender, data=orders_data) def MsgInstantBinaryOptionsMarketLaunch( self, @@ -622,6 +1204,15 @@ def MsgInstantBinaryOptionsMarketLaunch( min_quantity_tick_size: float, **kwargs, ): + """ + This method is deprecated and will be removed soon. + Please use `msg_instant_binary_options_market_launch` instead + """ + warn( + "This method is deprecated. Use msg_instant_binary_options_market_launch instead", + DeprecationWarning, + stacklevel=2, + ) scaled_maker_fee_rate = Decimal((maker_fee_rate * pow(10, 18))) maker_fee_to_bytes = bytes(str(scaled_maker_fee_rate), "utf-8") @@ -651,75 +1242,281 @@ def MsgInstantBinaryOptionsMarketLaunch( admin=kwargs.get("admin"), ) - def MsgCancelDerivativeOrder( + def msg_instant_binary_options_market_launch( self, - market_id: str, sender: str, - subaccount_id: str, - order_hash: Optional[str] = None, - cid: Optional[str] = None, - **kwargs, - ): - order_mask = self.get_order_mask(**kwargs) - - return injective_exchange_tx_pb.MsgCancelDerivativeOrder( + ticker: str, + oracle_symbol: str, + oracle_provider: str, + oracle_type: str, + oracle_scale_factor: int, + maker_fee_rate: Decimal, + taker_fee_rate: Decimal, + expiration_timestamp: int, + settlement_timestamp: int, + admin: str, + quote_denom: str, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch: + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_exchange_tx_pb.MsgInstantBinaryOptionsMarketLaunch( sender=sender, - market_id=market_id, - subaccount_id=subaccount_id, - order_hash=order_hash, - order_mask=order_mask, - cid=cid, + ticker=ticker, + oracle_symbol=oracle_symbol, + oracle_provider=oracle_provider, + oracle_type=injective_oracle_pb.OracleType.Value(oracle_type), + oracle_scale_factor=oracle_scale_factor, + maker_fee_rate=f"{chain_maker_fee_rate.normalize():f}", + taker_fee_rate=f"{chain_taker_fee_rate.normalize():f}", + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + admin=admin, + quote_denom=quote_token.denom, + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", ) - def MsgBatchCreateDerivativeLimitOrders(self, sender: str, orders: List): - return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders(sender=sender, orders=orders) + def MsgCreateBinaryOptionsLimitOrder( + self, + market_id: str, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: float, + quantity: float, + cid: Optional[str] = None, + **kwargs, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_create_binary_options_limit_order` instead + """ + warn( + "This method is deprecated. Use msg_create_binary_options_limit_order instead", + DeprecationWarning, + stacklevel=2, + ) + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) - def MsgBatchCancelDerivativeOrders(self, sender: str, data: List): - return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders(sender=sender, data=data) + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) - def MsgBatchUpdateOrders(self, sender: str, **kwargs): - return injective_exchange_tx_pb.MsgBatchUpdateOrders( + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + + return injective_exchange_tx_pb.MsgCreateBinaryOptionsLimitOrder( sender=sender, - subaccount_id=kwargs.get("subaccount_id"), - spot_market_ids_to_cancel_all=kwargs.get("spot_market_ids_to_cancel_all"), - derivative_market_ids_to_cancel_all=kwargs.get("derivative_market_ids_to_cancel_all"), - spot_orders_to_cancel=kwargs.get("spot_orders_to_cancel"), - derivative_orders_to_cancel=kwargs.get("derivative_orders_to_cancel"), - spot_orders_to_create=kwargs.get("spot_orders_to_create"), - derivative_orders_to_create=kwargs.get("derivative_orders_to_create"), - binary_options_orders_to_cancel=kwargs.get("binary_options_orders_to_cancel"), - binary_options_market_ids_to_cancel_all=kwargs.get("binary_options_market_ids_to_cancel_all"), - binary_options_orders_to_create=kwargs.get("binary_options_orders_to_create"), + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, + denom=kwargs.get("denom"), + ), ) - def MsgLiquidatePosition( + def msg_create_binary_options_limit_order( self, + market_id: str, sender: str, subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + denom: Optional[Denom] = None, + ) -> injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder: + return injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder( + sender=sender, + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + denom=denom, + ), + ) + + def MsgCreateBinaryOptionsMarketOrder( + self, market_id: str, - order: Optional[injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.DerivativeOrder] = None, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: float, + quantity: float, + cid: Optional[str] = None, + **kwargs, ): - return injective_exchange_tx_pb.MsgLiquidatePosition( - sender=sender, subaccount_id=subaccount_id, market_id=market_id, order=order + """ + This method is deprecated and will be removed soon. Please use `msg_create_binary_options_market_order` instead + """ + warn( + "This method is deprecated. Use msg_create_binary_options_market_order instead", + DeprecationWarning, + stacklevel=2, ) + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) - def MsgIncreasePositionMargin( + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + + return injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder( + sender=sender, + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, + denom=kwargs.get("denom"), + ), + ) + + def msg_create_binary_options_market_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + denom: Optional[Denom] = None, + ): + return injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder( + sender=sender, + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + denom=denom, + ), + ) + + def MsgCancelBinaryOptionsOrder( self, sender: str, - source_subaccount_id: str, - destination_subaccount_id: str, market_id: str, - amount: float, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, ): - market = self.derivative_markets[market_id] + """ + This method is deprecated and will be removed soon. Please use `msg_cancel_binary_options_order` instead + """ + warn( + "This method is deprecated. Use msg_cancel_binary_options_order instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder( + sender=sender, + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + ) - additional_margin = market.margin_to_chain_format(human_readable_value=Decimal(str(amount))) - return injective_exchange_tx_pb.MsgIncreasePositionMargin( + def msg_cancel_binary_options_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + is_conditional: Optional[bool] = False, + is_buy: Optional[bool] = False, + is_market_order: Optional[bool] = False, + ) -> injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder: + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) + + return injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder( sender=sender, - source_subaccount_id=source_subaccount_id, - destination_subaccount_id=destination_subaccount_id, market_id=market_id, - amount=str(int(additional_margin)), + subaccount_id=subaccount_id, + order_hash=order_hash, + order_mask=order_mask, + cid=cid, ) def MsgSubaccountTransfer( @@ -730,6 +1527,14 @@ def MsgSubaccountTransfer( amount: int, denom: str, ): + """ + This method is deprecated and will be removed soon. Please use `msg_subaccount_transfer` instead + """ + warn( + "This method is deprecated. Use msg_subaccount_transfer instead", + DeprecationWarning, + stacklevel=2, + ) be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgSubaccountTransfer( @@ -739,12 +1544,20 @@ def MsgSubaccountTransfer( amount=be_amount, ) - def MsgWithdraw(self, sender: str, subaccount_id: str, amount: float, denom: str): - be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + def msg_subaccount_transfer( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + amount: Decimal, + denom: str, + ) -> injective_exchange_tx_pb.MsgSubaccountTransfer: + be_amount = self.create_coin_amount(amount=amount, token_name=denom) - return injective_exchange_tx_pb.MsgWithdraw( + return injective_exchange_tx_pb.MsgSubaccountTransfer( sender=sender, - subaccount_id=subaccount_id, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, amount=be_amount, ) @@ -756,6 +1569,14 @@ def MsgExternalTransfer( amount: int, denom: str, ): + """ + This method is deprecated and will be removed soon. Please use `msg_external_transfer` instead + """ + warn( + "This method is deprecated. Use msg_external_transfer instead", + DeprecationWarning, + stacklevel=2, + ) coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgExternalTransfer( @@ -765,129 +1586,184 @@ def MsgExternalTransfer( amount=coin, ) - def MsgBid(self, sender: str, bid_amount: float, round: float): - be_amount = Decimal(str(bid_amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + def msg_external_transfer( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + amount: Decimal, + denom: str, + ) -> injective_exchange_tx_pb.MsgExternalTransfer: + coin = self.create_coin_amount(amount=amount, token_name=denom) - return injective_auction_tx_pb.MsgBid( + return injective_exchange_tx_pb.MsgExternalTransfer( sender=sender, - round=round, - bid_amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=coin, ) - def MsgGrantGeneric(self, granter: str, grantee: str, msg_type: str, expire_in: int): - auth = cosmos_authz_pb.GenericAuthorization(msg=msg_type) - any_auth = any_pb2.Any() - any_auth.Pack(auth, type_url_prefix="") - - grant = cosmos_authz_pb.Grant( - authorization=any_auth, - expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), + def MsgLiquidatePosition( + self, + sender: str, + subaccount_id: str, + market_id: str, + order: Optional[injective_exchange_pb.DerivativeOrder] = None, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_liquidate_position` instead + """ + warn( + "This method is deprecated. Use msg_liquidate_position instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgLiquidatePosition( + sender=sender, subaccount_id=subaccount_id, market_id=market_id, order=order ) - return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + def msg_liquidate_position( + self, + sender: str, + subaccount_id: str, + market_id: str, + order: Optional[injective_exchange_pb.DerivativeOrder] = None, + ) -> injective_exchange_tx_pb.MsgLiquidatePosition: + return injective_exchange_tx_pb.MsgLiquidatePosition( + sender=sender, subaccount_id=subaccount_id, market_id=market_id, order=order + ) - def MsgGrantTyped( + def msg_emergency_settle_market( self, - granter: str, - grantee: str, - msg_type: str, - expire_in: int, + sender: str, subaccount_id: str, - **kwargs, + market_id: str, + ) -> injective_exchange_tx_pb.MsgEmergencySettleMarket: + return injective_exchange_tx_pb.MsgEmergencySettleMarket( + sender=sender, subaccount_id=subaccount_id, market_id=market_id + ) + + def MsgIncreasePositionMargin( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + market_id: str, + amount: float, ): - auth = None - if msg_type == "CreateSpotLimitOrderAuthz": - auth = injective_authz_pb.CreateSpotLimitOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CreateSpotMarketOrderAuthz": - auth = injective_authz_pb.CreateSpotMarketOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCreateSpotLimitOrdersAuthz": - auth = injective_authz_pb.BatchCreateSpotLimitOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CancelSpotOrderAuthz": - auth = injective_authz_pb.CancelSpotOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCancelSpotOrdersAuthz": - auth = injective_authz_pb.BatchCancelSpotOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CreateDerivativeLimitOrderAuthz": - auth = injective_authz_pb.CreateDerivativeLimitOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CreateDerivativeMarketOrderAuthz": - auth = injective_authz_pb.CreateDerivativeMarketOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCreateDerivativeLimitOrdersAuthz": - auth = injective_authz_pb.BatchCreateDerivativeLimitOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CancelDerivativeOrderAuthz": - auth = injective_authz_pb.CancelDerivativeOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCancelDerivativeOrdersAuthz": - auth = injective_authz_pb.BatchCancelDerivativeOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchUpdateOrdersAuthz": - auth = injective_authz_pb.BatchUpdateOrdersAuthz( - subaccount_id=subaccount_id, - spot_markets=kwargs.get("spot_markets"), - derivative_markets=kwargs.get("derivative_markets"), - ) + """ + This method is deprecated and will be removed soon. Please use `msg_increase_position_margin` instead + """ + warn( + "This method is deprecated. Use msg_increase_position_margin instead", + DeprecationWarning, + stacklevel=2, + ) + market = self.derivative_markets[market_id] - any_auth = any_pb2.Any() - any_auth.Pack(auth, type_url_prefix="") + additional_margin = market.margin_to_chain_format(human_readable_value=Decimal(str(amount))) + return injective_exchange_tx_pb.MsgIncreasePositionMargin( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + market_id=market_id, + amount=str(int(additional_margin)), + ) - grant = cosmos_authz_pb.Grant( - authorization=any_auth, - expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), + def msg_increase_position_margin( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + market_id: str, + amount: Decimal, + ): + market = self.derivative_markets[market_id] + + additional_margin = market.margin_to_chain_format(human_readable_value=amount) + return injective_exchange_tx_pb.MsgIncreasePositionMargin( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + market_id=market_id, + amount=str(int(additional_margin)), ) - return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) - - def MsgExec(self, grantee: str, msgs: List): - any_msgs: List[any_pb2.Any] = [] - for msg in msgs: - any_msg = any_pb2.Any() - any_msg.Pack(msg, type_url_prefix="") - any_msgs.append(any_msg) + def MsgRewardsOptOut(self, sender: str): + """ + This method is deprecated and will be removed soon. Please use `msg_rewards_opt_out` instead + """ + warn( + "This method is deprecated. Use msg_rewards_opt_out instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgRewardsOptOut(sender=sender) - return cosmos_authz_tx_pb.MsgExec(grantee=grantee, msgs=any_msgs) + def msg_rewards_opt_out(self, sender: str) -> injective_exchange_tx_pb.MsgRewardsOptOut: + return injective_exchange_tx_pb.MsgRewardsOptOut(sender=sender) - def MsgRevoke(self, granter: str, grantee: str, msg_type: str): - return cosmos_authz_tx_pb.MsgRevoke(granter=granter, grantee=grantee, msg_type_url=msg_type) + def MsgAdminUpdateBinaryOptionsMarket( + self, + sender: str, + market_id: str, + status: str, + **kwargs, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_admin_update_binary_options_market` instead + """ + warn( + "This method is deprecated. Use msg_admin_update_binary_options_market instead", + DeprecationWarning, + stacklevel=2, + ) - def MsgRelayPriceFeedPrice(self, sender: list, base: list, quote: list, price: list): - return injective_oracle_tx_pb.MsgRelayPriceFeedPrice(sender=sender, base=base, quote=quote, price=price) + if kwargs.get("settlement_price") is not None: + scale_price = Decimal((kwargs.get("settlement_price") * pow(10, 18))) + price_to_bytes = bytes(str(scale_price), "utf-8") - def MsgSendToEth(self, denom: str, sender: str, eth_dest: str, amount: float, bridge_fee: float): - be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) - be_bridge_fee = self.create_coin_amount(amount=Decimal(str(bridge_fee)), token_name=denom) + else: + price_to_bytes = "" - return injective_peggy_tx_pb.MsgSendToEth( + return injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket( sender=sender, - eth_dest=eth_dest, - amount=be_amount, - bridge_fee=be_bridge_fee, + market_id=market_id, + settlement_price=price_to_bytes, + expiration_timestamp=kwargs.get("expiration_timestamp"), + settlement_timestamp=kwargs.get("settlement_timestamp"), + status=status, ) - def MsgDelegate(self, delegator_address: str, validator_address: str, amount: float): - be_amount = Decimal(str(amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + def msg_admin_update_binary_options_market( + self, + sender: str, + market_id: str, + status: str, + settlement_price: Optional[Decimal] = None, + expiration_timestamp: Optional[int] = None, + settlement_timestamp: Optional[int] = None, + ) -> injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket: + market = self.binary_option_markets[market_id] - return cosmos_staking_tx_pb.MsgDelegate( - delegator_address=delegator_address, - validator_address=validator_address, - amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), + if settlement_price is not None: + chain_settlement_price = market.price_to_chain_format(human_readable_value=settlement_price) + price_parameter = f"{chain_settlement_price.normalize():f}" + else: + price_parameter = None + + return injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket( + sender=sender, + market_id=market_id, + settlement_price=price_parameter, + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + status=status, ) + # endregion + + # region Insurance module def MsgCreateInsuranceFund( self, sender: str, @@ -941,38 +1817,53 @@ def MsgRequestRedemption( amount=self.coin(amount=amount, denom=share_denom), ) - def MsgVote( - self, - proposal_id: str, - voter: str, - option: int, - ): - return cosmos_gov_tx_pb.MsgVote(proposal_id=proposal_id, voter=voter, option=option) + # endregion - def MsgPrivilegedExecuteContract( - self, sender: str, contract: str, msg: str, **kwargs - ) -> injective_exchange_tx_pb.MsgPrivilegedExecuteContract: - return injective_exchange_tx_pb.MsgPrivilegedExecuteContract( - sender=sender, - contract_address=contract, - data=msg, - funds=kwargs.get("funds") # funds is a string of Coin strings, comma separated, - # e.g. 100000inj,20000000000usdt + # region Oracle module + def MsgRelayProviderPrices(self, sender: str, provider: str, symbols: list, prices: list): + oracle_prices = [] + + for price in prices: + scale_price = Decimal((price) * pow(10, 18)) + price_to_bytes = bytes(str(scale_price), "utf-8") + oracle_prices.append(price_to_bytes) + + return injective_oracle_tx_pb.MsgRelayProviderPrices( + sender=sender, provider=provider, symbols=symbols, prices=oracle_prices ) - def MsgInstantiateContract( - self, sender: str, admin: str, code_id: int, label: str, message: bytes, **kwargs - ) -> wasm_tx_pb.MsgInstantiateContract: - return wasm_tx_pb.MsgInstantiateContract( + def MsgRelayPriceFeedPrice(self, sender: list, base: list, quote: list, price: list): + return injective_oracle_tx_pb.MsgRelayPriceFeedPrice(sender=sender, base=base, quote=quote, price=price) + + # endregion + + # region Peggy module + def MsgSendToEth(self, denom: str, sender: str, eth_dest: str, amount: float, bridge_fee: float): + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + be_bridge_fee = self.create_coin_amount(amount=Decimal(str(bridge_fee)), token_name=denom) + + return injective_peggy_tx_pb.MsgSendToEth( sender=sender, - admin=admin, - code_id=code_id, - label=label, - msg=message, - funds=kwargs.get("funds"), # funds is a list of cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin. - # The coins in the list must be sorted in alphabetical order by denoms. + eth_dest=eth_dest, + amount=be_amount, + bridge_fee=be_bridge_fee, + ) + + # endregion + + # region Staking module + def MsgDelegate(self, delegator_address: str, validator_address: str, amount: float): + be_amount = Decimal(str(amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return cosmos_staking_tx_pb.MsgDelegate( + delegator_address=delegator_address, + validator_address=validator_address, + amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), ) + # endregion + + # region Tokenfactory module def msg_create_denom( self, sender: str, @@ -990,14 +1881,14 @@ def msg_create_denom( def msg_mint( self, sender: str, - amount: cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin, + amount: base_coin_pb.Coin, ) -> token_factory_tx_pb.MsgMint: return token_factory_tx_pb.MsgMint(sender=sender, amount=amount) def msg_burn( self, sender: str, - amount: cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin, + amount: base_coin_pb.Coin, ) -> token_factory_tx_pb.MsgBurn: return token_factory_tx_pb.MsgBurn(sender=sender, amount=amount) @@ -1047,14 +1938,108 @@ def msg_change_admin( new_admin=new_admin, ) - def msg_execute_contract_compat(self, sender: str, contract: str, msg: str, funds: str): - return wasmx_tx_pb.MsgExecuteContractCompat( + # endregion + + # region Wasm module + def MsgInstantiateContract( + self, sender: str, admin: str, code_id: int, label: str, message: bytes, **kwargs + ) -> wasm_tx_pb.MsgInstantiateContract: + return wasm_tx_pb.MsgInstantiateContract( + sender=sender, + admin=admin, + code_id=code_id, + label=label, + msg=message, + funds=kwargs.get("funds"), # funds is a list of base_coin_pb.Coin. + # The coins in the list must be sorted in alphabetical order by denoms. + ) + + def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): + return wasm_tx_pb.MsgExecuteContract( sender=sender, contract=contract, - msg=msg, - funds=funds, + msg=bytes(msg, "utf-8"), + funds=kwargs.get("funds") # funds is a list of base_coin_pb.Coin. + # The coins in the list must be sorted in alphabetical order by denoms. + ) + + # endregion + + def MsgGrantTyped( + self, + granter: str, + grantee: str, + msg_type: str, + expire_in: int, + subaccount_id: str, + **kwargs, + ): + auth = None + if msg_type == "CreateSpotLimitOrderAuthz": + auth = injective_authz_pb.CreateSpotLimitOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CreateSpotMarketOrderAuthz": + auth = injective_authz_pb.CreateSpotMarketOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCreateSpotLimitOrdersAuthz": + auth = injective_authz_pb.BatchCreateSpotLimitOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CancelSpotOrderAuthz": + auth = injective_authz_pb.CancelSpotOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCancelSpotOrdersAuthz": + auth = injective_authz_pb.BatchCancelSpotOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CreateDerivativeLimitOrderAuthz": + auth = injective_authz_pb.CreateDerivativeLimitOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CreateDerivativeMarketOrderAuthz": + auth = injective_authz_pb.CreateDerivativeMarketOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCreateDerivativeLimitOrdersAuthz": + auth = injective_authz_pb.BatchCreateDerivativeLimitOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CancelDerivativeOrderAuthz": + auth = injective_authz_pb.CancelDerivativeOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCancelDerivativeOrdersAuthz": + auth = injective_authz_pb.BatchCancelDerivativeOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchUpdateOrdersAuthz": + auth = injective_authz_pb.BatchUpdateOrdersAuthz( + subaccount_id=subaccount_id, + spot_markets=kwargs.get("spot_markets"), + derivative_markets=kwargs.get("derivative_markets"), + ) + + any_auth = any_pb2.Any() + any_auth.Pack(auth, type_url_prefix="") + + grant = cosmos_authz_pb.Grant( + authorization=any_auth, + expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), ) + return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + + def MsgVote( + self, + proposal_id: str, + voter: str, + option: int, + ): + return cosmos_gov_tx_pb.MsgVote(proposal_id=proposal_id, voter=voter, option=option) + def chain_stream_bank_balances_filter( self, accounts: Optional[List[str]] = None ) -> chain_stream_query.BankBalancesFilter: @@ -1144,7 +2129,7 @@ def MsgWithdrawValidatorCommission(self, validator_address: str): def msg_withdraw_validator_commission(self, validator_address: str): return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) - def msg_fund_community_pool(self, amounts: List[cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin], depositor: str): + def msg_fund_community_pool(self, amounts: List[base_coin_pb.Coin], depositor: str): return cosmos_distribution_tx_pb.MsgFundCommunityPool(amount=amounts, depositor=depositor) def msg_update_distribution_params(self, authority: str, community_tax: str, withdraw_address_enabled: bool): @@ -1154,9 +2139,7 @@ def msg_update_distribution_params(self, authority: str, community_tax: str, wit ) return cosmos_distribution_tx_pb.MsgUpdateParams(authority=authority, params=params) - def msg_community_pool_spend( - self, authority: str, recipient: str, amount: List[cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin] - ): + def msg_community_pool_spend(self, authority: str, recipient: str, amount: List[base_coin_pb.Coin]): return cosmos_distribution_tx_pb.MsgCommunityPoolSpend(authority=authority, recipient=recipient, amount=amount) # data field format: [request-msg-header][raw-byte-msg-response] @@ -1369,3 +2352,61 @@ def _initialize_markets_and_tokens_from_files(self): self.spot_markets = spot_markets self.derivative_markets = derivative_markets self.binary_option_markets = dict() + + def _order_mask(self, is_conditional: bool, is_buy: bool, is_market_order: bool) -> int: + order_mask = 0 + + if is_conditional: + order_mask += injective_exchange_pb.OrderMask.CONDITIONAL + else: + order_mask += injective_exchange_pb.OrderMask.REGULAR + + if is_buy: + order_mask += injective_exchange_pb.OrderMask.DIRECTION_BUY_OR_HIGHER + else: + order_mask += injective_exchange_pb.OrderMask.DIRECTION_SELL_OR_LOWER + + if is_market_order: + order_mask += injective_exchange_pb.OrderMask.TYPE_MARKET + else: + order_mask += injective_exchange_pb.OrderMask.TYPE_LIMIT + + if order_mask == 0: + order_mask = 1 + + return order_mask + + def _basic_derivative_order( + self, + market_id: str, + subaccount_id: str, + fee_recipient: str, + chain_price: Decimal, + chain_quantity: Decimal, + chain_margin: Decimal, + order_type: str, + cid: Optional[str] = None, + chain_trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_pb.DerivativeOrder: + formatted_quantity = f"{chain_quantity.normalize():f}" + formatted_price = f"{chain_price.normalize():f}" + formatted_margin = f"{chain_margin.normalize():f}" + + trigger_price = chain_trigger_price or Decimal(0) + formatted_trigger_price = f"{trigger_price.normalize():f}" + + chain_order_type = injective_exchange_pb.OrderType.Value(order_type) + + return injective_exchange_pb.DerivativeOrder( + market_id=market_id, + order_info=injective_exchange_pb.OrderInfo( + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=formatted_price, + quantity=formatted_quantity, + cid=cid, + ), + order_type=chain_order_type, + margin=formatted_margin, + trigger_price=formatted_trigger_price, + ) diff --git a/pyinjective/core/market.py b/pyinjective/core/market.py index 2bd4fe1b..66063130 100644 --- a/pyinjective/core/market.py +++ b/pyinjective/core/market.py @@ -169,6 +169,17 @@ def price_to_chain_format(self, human_readable_value: Decimal, special_denom: Op return extended_chain_formatted_value + def margin_to_chain_format(self, human_readable_value: Decimal, special_denom: Optional[Denom] = None) -> Decimal: + decimals = self.quote_token.decimals if special_denom is None else special_denom.quote + min_quantity_tick_size = ( + self.min_quantity_tick_size if special_denom is None else special_denom.min_quantity_tick_size + ) + chain_formatted_value = human_readable_value * Decimal(f"1e{decimals}") + quantized_value = (chain_formatted_value // min_quantity_tick_size) * min_quantity_tick_size + extended_chain_formatted_value = quantized_value * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return extended_chain_formatted_value + def calculate_margin_in_chain_format( self, human_readable_quantity: Decimal, diff --git a/tests/core/test_gas_limit_estimator.py b/tests/core/test_gas_limit_estimator.py index 916c47a9..293f5f25 100644 --- a/tests/core/test_gas_limit_estimator.py +++ b/tests/core/test_gas_limit_estimator.py @@ -24,26 +24,24 @@ def test_estimation_for_batch_create_spot_limit_orders(self): spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=5, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("5"), + quantity=Decimal("1"), + order_type="BUY", ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=4, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("4"), + quantity=Decimal("1"), + order_type="BUY", ), ] - message = composer.MsgBatchCreateSpotLimitOrders(sender="sender", orders=orders) + message = composer.msg_batch_create_spot_limit_orders(sender="sender", orders=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 50000 @@ -55,23 +53,23 @@ def test_estimation_for_batch_cancel_spot_orders(self): spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", ), ] - message = composer.MsgBatchCancelSpotOrders(sender="sender", data=orders) + message = composer.msg_batch_cancel_spot_orders(sender="sender", orders_data=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 50000 @@ -83,28 +81,26 @@ def test_estimation_for_batch_create_derivative_limit_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=3, - quantity=1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(3), + quantity=Decimal(1), + margin=Decimal(3), + order_type="BUY", ), - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=20, - quantity=1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(20), + quantity=Decimal(1), + margin=Decimal(20), + order_type="SELL", ), ] - message = composer.MsgBatchCreateDerivativeLimitOrders(sender="sender", orders=orders) + message = composer.msg_batch_create_derivative_limit_orders(sender="sender", orders=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 70_000 @@ -116,23 +112,23 @@ def test_estimation_for_batch_cancel_derivative_orders(self): spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", ), ] - message = composer.MsgBatchCancelDerivativeOrders(sender="sender", data=orders) + message = composer.msg_batch_cancel_derivative_orders(sender="sender", orders_data=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 60_000 @@ -144,23 +140,21 @@ def test_estimation_for_batch_update_orders_to_create_spot_orders(self): market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.SpotOrder( + composer.spot_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=5, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("5"), + quantity=Decimal("1"), + order_type="BUY", ), - composer.SpotOrder( + composer.spot_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=4, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("4"), + quantity=Decimal("1"), + order_type="BUY", ), ] message = composer.MsgBatchUpdateOrders( @@ -181,25 +175,23 @@ def test_estimation_for_batch_update_orders_to_create_derivative_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=3, - quantity=1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(3), + quantity=Decimal(1), + margin=Decimal(3), + order_type="BUY", ), - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=20, - quantity=1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(20), + quantity=Decimal(1), + margin=Decimal(20), + order_type="SELL", ), ] message = composer.MsgBatchUpdateOrders( @@ -238,25 +230,23 @@ def test_estimation_for_batch_update_orders_to_create_binary_orders(self, usdt_t ) composer.binary_option_markets[market.id] = market orders = [ - composer.BinaryOptionsOrder( + composer.binary_options_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=3, - quantity=1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(3), + quantity=Decimal(1), + margin=Decimal(3), + order_type="BUY", ), - composer.BinaryOptionsOrder( + composer.binary_options_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=20, - quantity=1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(20), + quantity=Decimal(1), + margin=Decimal(20), + order_type="SELL", ), ] message = composer.MsgBatchUpdateOrders( @@ -278,17 +268,17 @@ def test_estimation_for_batch_update_orders_to_cancel_spot_orders(self): market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -312,17 +302,17 @@ def test_estimation_for_batch_update_orders_to_cancel_derivative_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -346,17 +336,17 @@ def test_estimation_for_batch_update_orders_to_cancel_binary_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -441,14 +431,13 @@ def test_estimation_for_exec_message(self): market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.SpotOrder( + composer.spot_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=5, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("5"), + quantity=Decimal("1"), + order_type="BUY", ), ] inner_message = composer.MsgBatchUpdateOrders( @@ -510,15 +499,14 @@ def test_estimation_for_governance_message(self): def test_estimation_for_generic_exchange_message(self): composer = Composer(network="testnet") - message = composer.MsgCreateSpotLimitOrder( + message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) estimator = GasLimitEstimator.for_message(message=message) diff --git a/tests/core/test_market.py b/tests/core/test_market.py index ede8aea5..48c2f5e5 100644 --- a/tests/core/test_market.py +++ b/tests/core/test_market.py @@ -248,6 +248,42 @@ def test_convert_price_to_chain_format_without_fixed_denom(self, first_match_bet assert quantized_chain_format_value == chain_value + def test_convert_margin_to_chain_format_with_fixed_denom(self, first_match_bet_market: BinaryOptionMarket): + original_quantity = Decimal("123.456789") + fixed_denom = Denom( + description="Fixed denom", + base=2, + quote=4, + min_quantity_tick_size=100, + min_price_tick_size=10000, + ) + + chain_value = first_match_bet_market.margin_to_chain_format( + human_readable_value=original_quantity, + special_denom=fixed_denom, + ) + price_decimals = fixed_denom.quote + expected_value = original_quantity * Decimal(f"1e{price_decimals}") + quantized_value = (expected_value // Decimal(str(fixed_denom.min_quantity_tick_size))) * Decimal( + str(fixed_denom.min_quantity_tick_size) + ) + quantized_chain_format_value = quantized_value * Decimal("1e18") + + assert quantized_chain_format_value == chain_value + + def test_convert_margin_to_chain_format_without_fixed_denom(self, first_match_bet_market: BinaryOptionMarket): + original_quantity = Decimal("123.456789") + + chain_value = first_match_bet_market.margin_to_chain_format(human_readable_value=original_quantity) + price_decimals = first_match_bet_market.quote_token.decimals + expected_value = original_quantity * Decimal(f"1e{price_decimals}") + quantized_value = ( + expected_value // first_match_bet_market.min_quantity_tick_size + ) * first_match_bet_market.min_quantity_tick_size + quantized_chain_format_value = quantized_value * Decimal("1e18") + + assert quantized_chain_format_value == chain_value + def test_calculate_margin_for_buy_with_fixed_denom(self, first_match_bet_market: BinaryOptionMarket): original_quantity = Decimal("123.456789") original_price = Decimal("0.6789") diff --git a/tests/core/test_message_based_transaction_fee_calculator.py b/tests/core/test_message_based_transaction_fee_calculator.py index 23e263c9..b1d774e0 100644 --- a/tests/core/test_message_based_transaction_fee_calculator.py +++ b/tests/core/test_message_based_transaction_fee_calculator.py @@ -117,15 +117,14 @@ async def test_gas_fee_for_exchange_message(self): gas_price=5_000_000, ) - message = composer.MsgCreateSpotLimitOrder( + message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) transaction = Transaction() transaction.with_messages(message) @@ -148,15 +147,14 @@ async def test_gas_fee_for_msg_exec_message(self): gas_price=5_000_000, ) - inner_message = composer.MsgCreateSpotLimitOrder( + inner_message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) message = composer.MsgExec(grantee="grantee", msgs=[inner_message]) transaction = Transaction() @@ -184,15 +182,14 @@ async def test_gas_fee_for_two_messages_in_one_transaction(self): gas_price=5_000_000, ) - inner_message = composer.MsgCreateSpotLimitOrder( + inner_message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) message = composer.MsgExec(grantee="grantee", msgs=[inner_message]) diff --git a/tests/test_composer.py b/tests/test_composer.py index a0cca2ab..2dcbd056 100644 --- a/tests/test_composer.py +++ b/tests/test_composer.py @@ -2,12 +2,11 @@ from decimal import Decimal import pytest +from google.protobuf import json_format from pyinjective.composer import Composer -from pyinjective.core.market import BinaryOptionMarket, DerivativeMarket, SpotMarket +from pyinjective.constant import ADDITIONAL_CHAIN_FORMAT_DECIMALS from pyinjective.core.network import Network -from pyinjective.proto.injective.exchange.v1beta1 import exchange_pb2 -from pyinjective.utils.denom import Denom from tests.model_fixtures.markets_fixtures import btc_usdt_perp_market # noqa: F401 from tests.model_fixtures.markets_fixtures import first_match_bet_market # noqa: F401 from tests.model_fixtures.markets_fixtures import inj_token # noqa: F401 @@ -57,211 +56,6 @@ def test_composer_initialization_from_ini_files(self): assert 6 == inj_usdt_spot_market.quote_token.decimals assert 6 == inj_usdt_perp_market.quote_token.decimals - def test_buy_spot_order_creation(self, basic_composer: Composer, inj_usdt_spot_market: SpotMarket): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - order = basic_composer.SpotOrder( - market_id=inj_usdt_spot_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - ) - - price_decimals = inj_usdt_spot_market.quote_token.decimals - inj_usdt_spot_market.base_token.decimals - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // inj_usdt_spot_market.min_price_tick_size) - * inj_usdt_spot_market.min_price_tick_size - * Decimal("1e18") - ) - chain_format_quantity = Decimal(str(quantity)) * Decimal(f"1e{inj_usdt_spot_market.base_token.decimals}") - expected_quantity = ( - (chain_format_quantity // inj_usdt_spot_market.min_quantity_tick_size) - * inj_usdt_spot_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert order.market_id == inj_usdt_spot_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.trigger_price == "0" - - def test_buy_derivative_order_creation(self, basic_composer: Composer, btc_usdt_perp_market: DerivativeMarket): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - leverage = 2 - order = basic_composer.DerivativeOrder( - market_id=btc_usdt_perp_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - leverage=leverage, - ) - - price_decimals = btc_usdt_perp_market.quote_token.decimals - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // btc_usdt_perp_market.min_price_tick_size) - * btc_usdt_perp_market.min_price_tick_size - * Decimal("1e18") - ) - chain_format_quantity = Decimal(str(quantity)) - expected_quantity = ( - (chain_format_quantity // btc_usdt_perp_market.min_quantity_tick_size) - * btc_usdt_perp_market.min_quantity_tick_size - * Decimal("1e18") - ) - chain_format_margin = (chain_format_quantity * chain_format_price) / Decimal(leverage) - expected_margin = ( - (chain_format_margin // btc_usdt_perp_market.min_quantity_tick_size) - * btc_usdt_perp_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert order.market_id == btc_usdt_perp_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.margin == str(int(expected_margin)) - assert order.trigger_price == "0" - - def test_increase_position_margin(self, basic_composer: Composer, btc_usdt_perp_market: DerivativeMarket): - sender = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - amount = 1587.789 - message = basic_composer.MsgIncreasePositionMargin( - sender=sender, - source_subaccount_id="1", - destination_subaccount_id="2", - market_id=btc_usdt_perp_market.id, - amount=amount, - ) - - price_decimals = btc_usdt_perp_market.quote_token.decimals - chain_format_margin = Decimal(str(amount)) * Decimal(f"1e{price_decimals}") - expected_margin = ( - (chain_format_margin // btc_usdt_perp_market.min_quantity_tick_size) - * btc_usdt_perp_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert message.market_id == btc_usdt_perp_market.id - assert message.sender == sender - assert message.source_subaccount_id == "1" - assert message.destination_subaccount_id == "2" - assert message.amount == str(int(expected_margin)) - - def test_buy_binary_option_order_creation_with_fixed_denom( - self, basic_composer: Composer, first_match_bet_market: BinaryOptionMarket - ): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - fixed_denom = Denom( - description="Fixed denom", - base=2, - quote=6, - min_price_tick_size=1000, - min_quantity_tick_size=10000, - ) - - order = basic_composer.BinaryOptionsOrder( - market_id=first_match_bet_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - denom=fixed_denom, - ) - - price_decimals = fixed_denom.quote - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // Decimal(str(fixed_denom.min_price_tick_size))) - * Decimal(str(fixed_denom.min_price_tick_size)) - * Decimal("1e18") - ) - quantity_decimals = fixed_denom.base - chain_format_quantity = Decimal(str(quantity)) * Decimal(f"1e{quantity_decimals}") - expected_quantity = ( - (chain_format_quantity // Decimal(str(fixed_denom.min_quantity_tick_size))) - * Decimal(str(fixed_denom.min_quantity_tick_size)) - * Decimal("1e18") - ) - chain_format_margin = chain_format_quantity * chain_format_price - expected_margin = ( - (chain_format_margin // Decimal(str(fixed_denom.min_quantity_tick_size))) - * Decimal(str(fixed_denom.min_quantity_tick_size)) - * Decimal("1e18") - ) - - assert order.market_id == first_match_bet_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.margin == str(int(expected_margin)) - assert order.trigger_price == "0" - - def test_buy_binary_option_order_creation_without_fixed_denom( - self, - basic_composer: Composer, - first_match_bet_market: BinaryOptionMarket, - ): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - - order = basic_composer.BinaryOptionsOrder( - market_id=first_match_bet_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - ) - - price_decimals = first_match_bet_market.quote_token.decimals - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // first_match_bet_market.min_price_tick_size) - * first_match_bet_market.min_price_tick_size - * Decimal("1e18") - ) - chain_format_quantity = Decimal(str(quantity)) - expected_quantity = ( - (chain_format_quantity // first_match_bet_market.min_quantity_tick_size) - * first_match_bet_market.min_quantity_tick_size - * Decimal("1e18") - ) - chain_format_margin = chain_format_quantity * chain_format_price - expected_margin = ( - (chain_format_margin // first_match_bet_market.min_quantity_tick_size) - * first_match_bet_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert order.market_id == first_match_bet_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.margin == str(int(expected_margin)) - assert order.trigger_price == "0" - def test_msg_create_denom(self, basic_composer: Composer): sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" subdenom = "inj-test" @@ -380,3 +174,1259 @@ def test_msg_execute_contract_compat(self, basic_composer): assert message.contract == contract assert message.msg == msg assert message.funds == funds + + def test_msg_deposit(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=Decimal(amount)) + + message = basic_composer.msg_deposit( + sender=sender, + subaccount_id=subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_withdraw(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=Decimal(amount)) + + message = basic_composer.msg_withdraw( + sender=sender, + subaccount_id=subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_spot_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "INJ/USDT" + base_denom = "INJ" + quote_denom = "USDT" + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + + base_token = basic_composer.tokens[base_denom] + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals - base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal( + f"1e{base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + + message = basic_composer.msg_instant_spot_market_launch( + sender=sender, + ticker=ticker, + base_denom=base_denom, + quote_denom=quote_denom, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "baseDenom": base_token.denom, + "quoteDenom": quote_token.denom, + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_perpetual_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "BTC/INJ PERP" + quote_denom = "INJ" + oracle_base = "BTC" + oracle_quote = "INJ" + oracle_scale_factor = 6 + oracle_type = "Band" + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + maker_fee_rate = Decimal("0.001") + taker_fee_rate = Decimal("-0.002") + initial_margin_ratio = Decimal("0.05") + maintenance_margin_ratio = Decimal("0.03") + + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + message = basic_composer.msg_instant_perpetual_market_launch( + sender=sender, + ticker=ticker, + quote_denom=quote_denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=oracle_type, + maker_fee_rate=maker_fee_rate, + taker_fee_rate=taker_fee_rate, + initial_margin_ratio=initial_margin_ratio, + maintenance_margin_ratio=maintenance_margin_ratio, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "quoteDenom": quote_token.denom, + "oracleBase": oracle_base, + "oracleQuote": oracle_quote, + "oracleScaleFactor": oracle_scale_factor, + "oracleType": oracle_type, + "makerFeeRate": f"{expected_maker_fee_rate.normalize():f}", + "takerFeeRate": f"{expected_taker_fee_rate.normalize():f}", + "initialMarginRatio": f"{expected_initial_margin_ratio.normalize():f}", + "maintenanceMarginRatio": f"{expected_maintenance_margin_ratio.normalize():f}", + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_expiry_futures_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "BTC/INJ PERP" + quote_denom = "INJ" + oracle_base = "BTC" + oracle_quote = "INJ" + oracle_scale_factor = 6 + oracle_type = "Band" + expiry = 1630000000 + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + maker_fee_rate = Decimal("0.001") + taker_fee_rate = Decimal("-0.002") + initial_margin_ratio = Decimal("0.05") + maintenance_margin_ratio = Decimal("0.03") + + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + message = basic_composer.msg_instant_expiry_futures_market_launch( + sender=sender, + ticker=ticker, + quote_denom=quote_denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=oracle_type, + expiry=expiry, + maker_fee_rate=maker_fee_rate, + taker_fee_rate=taker_fee_rate, + initial_margin_ratio=initial_margin_ratio, + maintenance_margin_ratio=maintenance_margin_ratio, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "quoteDenom": quote_token.denom, + "oracleBase": oracle_base, + "oracleQuote": oracle_quote, + "oracleType": oracle_type, + "oracleScaleFactor": oracle_scale_factor, + "expiry": str(expiry), + "makerFeeRate": f"{expected_maker_fee_rate.normalize():f}", + "takerFeeRate": f"{expected_taker_fee_rate.normalize():f}", + "initialMarginRatio": f"{expected_initial_margin_ratio.normalize():f}", + "maintenanceMarginRatio": f"{expected_maintenance_margin_ratio.normalize():f}", + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_spot_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.spot_order( + market_id=spot_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = spot_market.price_to_chain_format(human_readable_value=price) + expected_quantity = spot_market.quantity_to_chain_format(human_readable_value=quantity) + expected_trigger_price = spot_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_order = { + "marketId": spot_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=order, + including_default_value_fields=True, + ) + assert dict_message == expected_order + + def test_derivative_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.derivative_order( + market_id=derivative_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = derivative_market.price_to_chain_format(human_readable_value=price) + expected_quantity = derivative_market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = derivative_market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = derivative_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_order = { + "marketId": derivative_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "margin": f"{expected_margin.normalize():f}", + "triggerPrice": f"{expected_trigger_price.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=order, + including_default_value_fields=True, + ) + assert dict_message == expected_order + + def test_msg_create_spot_limit_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_spot_limit_order( + market_id=spot_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = spot_market.price_to_chain_format(human_readable_value=price) + expected_quantity = spot_market.quantity_to_chain_format(human_readable_value=quantity) + expected_trigger_price = spot_market.price_to_chain_format(human_readable_value=trigger_price) + + assert "injective.exchange.v1beta1.MsgCreateSpotLimitOrder" == message.DESCRIPTOR.full_name + expected_message = { + "sender": sender, + "order": { + "marketId": spot_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_create_spot_limit_orders(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.spot_order( + market_id=spot_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + message = basic_composer.msg_batch_create_spot_limit_orders( + sender=sender, + orders=[order], + ) + + expected_message = { + "sender": sender, + "orders": [json_format.MessageToDict(message=order, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_spot_market_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_spot_market_order( + market_id=spot_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = spot_market.price_to_chain_format(human_readable_value=price) + expected_quantity = spot_market.quantity_to_chain_format(human_readable_value=quantity) + expected_trigger_price = spot_market.price_to_chain_format(human_readable_value=trigger_price) + + assert "injective.exchange.v1beta1.MsgCreateSpotMarketOrder" == message.DESCRIPTOR.full_name + expected_message = { + "sender": sender, + "order": { + "marketId": spot_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_cancel_spot_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + order_hash = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + cid = "test_cid" + + message = basic_composer.msg_cancel_spot_order( + market_id=spot_market.id, + sender=sender, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + ) + + expected_message = { + "sender": sender, + "marketId": spot_market.id, + "subaccountId": subaccount_id, + "orderHash": order_hash, + "cid": cid, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_cancel_spot_orders(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + + order_data = basic_composer.order_data( + market_id=spot_market.id, + subaccount_id=subaccount_id, + order_hash="0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000", + ) + + message = basic_composer.msg_batch_cancel_spot_orders( + sender=sender, + orders_data=[order_data], + ) + + assert "injective.exchange.v1beta1.MsgBatchCancelSpotOrders" == message.DESCRIPTOR.full_name + expected_message = { + "sender": sender, + "data": [json_format.MessageToDict(message=order_data, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_update_orders(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + derivative_market = list(basic_composer.derivative_markets.values())[0] + binary_options_market = list(basic_composer.binary_option_markets.values())[0] + + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + spot_market_id = spot_market.id + derivative_market_id = derivative_market.id + binary_options_market_id = binary_options_market.id + spot_order_to_cancel = basic_composer.order_data( + market_id=spot_market_id, + subaccount_id=subaccount_id, + order_hash="0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000", + ) + derivative_order_to_cancel = basic_composer.order_data( + market_id=derivative_market_id, + subaccount_id=subaccount_id, + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", + ) + binary_options_order_to_cancel = basic_composer.order_data( + market_id=binary_options_market_id, + subaccount_id=subaccount_id, + order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", + ) + spot_order_to_create = basic_composer.spot_order( + market_id=spot_market_id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + order_type="BUY", + cid="test_cid", + trigger_price=Decimal("43.5"), + ) + derivative_order_to_create = basic_composer.derivative_order( + market_id=derivative_market_id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + margin=Decimal("36.1") * Decimal("100"), + order_type="BUY", + ) + binary_options_order_to_create = basic_composer.binary_options_order( + market_id=binary_options_market_id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + margin=Decimal("36.1") * Decimal("100"), + order_type="BUY", + ) + + message = basic_composer.msg_batch_update_orders( + sender=sender, + subaccount_id=subaccount_id, + spot_market_ids_to_cancel_all=[spot_market_id], + derivative_market_ids_to_cancel_all=[derivative_market_id], + spot_orders_to_cancel=[spot_order_to_cancel], + derivative_orders_to_cancel=[derivative_order_to_cancel], + spot_orders_to_create=[spot_order_to_create], + derivative_orders_to_create=[derivative_order_to_create], + binary_options_orders_to_cancel=[binary_options_order_to_cancel], + binary_options_market_ids_to_cancel_all=[binary_options_market_id], + binary_options_orders_to_create=[binary_options_order_to_create], + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "spotMarketIdsToCancelAll": [spot_market_id], + "derivativeMarketIdsToCancelAll": [derivative_market_id], + "spotOrdersToCancel": [ + json_format.MessageToDict(message=spot_order_to_cancel, including_default_value_fields=True) + ], + "derivativeOrdersToCancel": [ + json_format.MessageToDict(message=derivative_order_to_cancel, including_default_value_fields=True) + ], + "spotOrdersToCreate": [ + json_format.MessageToDict(message=spot_order_to_create, including_default_value_fields=True) + ], + "derivativeOrdersToCreate": [ + json_format.MessageToDict(message=derivative_order_to_create, including_default_value_fields=True) + ], + "binaryOptionsOrdersToCancel": [ + json_format.MessageToDict(message=binary_options_order_to_cancel, including_default_value_fields=True) + ], + "binaryOptionsMarketIdsToCancelAll": [binary_options_market_id], + "binaryOptionsOrdersToCreate": [ + json_format.MessageToDict(message=binary_options_order_to_create, including_default_value_fields=True) + ], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_privileged_execute_contract(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + contract_address = "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7" + data = "test_data" + funds = "100inj,420peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7" + + message = basic_composer.msg_privileged_execute_contract( + sender=sender, + contract_address=contract_address, + data=data, + funds=funds, + ) + + expected_message = { + "sender": sender, + "funds": funds, + "contractAddress": contract_address, + "data": data, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_derivative_limit_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_derivative_limit_order( + market_id=derivative_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = derivative_market.price_to_chain_format(human_readable_value=price) + expected_quantity = derivative_market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = derivative_market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = derivative_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": derivative_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_create_derivative_limit_orders(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.derivative_order( + market_id=derivative_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=price * quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + message = basic_composer.msg_batch_create_derivative_limit_orders( + sender=sender, + orders=[order], + ) + + expected_message = { + "sender": sender, + "orders": [json_format.MessageToDict(message=order, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_derivative_market_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_derivative_market_order( + market_id=derivative_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = derivative_market.price_to_chain_format(human_readable_value=price) + expected_quantity = derivative_market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = derivative_market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = derivative_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": derivative_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_cancel_derivative_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + order_hash = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + cid = "test_cid" + is_conditional = False + is_buy = True + is_market_order = False + + expected_order_mask = basic_composer._order_mask( + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + message = basic_composer.msg_cancel_derivative_order( + market_id=derivative_market.id, + sender=sender, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + expected_message = { + "sender": sender, + "marketId": derivative_market.id, + "subaccountId": subaccount_id, + "orderHash": order_hash, + "orderMask": expected_order_mask, + "cid": cid, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_cancel_derivative_orders(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + + order_data = basic_composer.order_data( + market_id=derivative_market.id, + subaccount_id=subaccount_id, + order_hash="0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000", + ) + + message = basic_composer.msg_batch_cancel_derivative_orders( + sender=sender, + orders_data=[order_data], + ) + + expected_message = { + "sender": sender, + "data": [json_format.MessageToDict(message=order_data, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_binary_options_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "B2500/INJ" + oracle_symbol = "B2500_1/INJ" + oracle_provider = "Injective" + oracle_scale_factor = 6 + oracle_type = "Band" + quote_denom = "INJ" + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + maker_fee_rate = Decimal("0.001") + taker_fee_rate = Decimal("-0.002") + expiration_timestamp = 1630000000 + settlement_timestamp = 1660000000 + admin = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + message = basic_composer.msg_instant_binary_options_market_launch( + sender=sender, + ticker=ticker, + oracle_symbol=oracle_symbol, + oracle_provider=oracle_provider, + oracle_type=oracle_type, + oracle_scale_factor=oracle_scale_factor, + maker_fee_rate=maker_fee_rate, + taker_fee_rate=taker_fee_rate, + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + admin=admin, + quote_denom=quote_denom, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "oracleSymbol": oracle_symbol, + "oracleProvider": oracle_provider, + "oracleType": oracle_type, + "oracleScaleFactor": oracle_scale_factor, + "makerFeeRate": f"{expected_maker_fee_rate.normalize():f}", + "takerFeeRate": f"{expected_taker_fee_rate.normalize():f}", + "expirationTimestamp": str(expiration_timestamp), + "settlementTimestamp": str(settlement_timestamp), + "admin": admin, + "quoteDenom": quote_token.denom, + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_binary_options_limit_order(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_binary_options_limit_order( + market_id=market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = market.price_to_chain_format(human_readable_value=price) + expected_quantity = market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_binary_options_market_order(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_binary_options_market_order( + market_id=market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = market.price_to_chain_format(human_readable_value=price) + expected_quantity = market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_cancel_derivative_order(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + order_hash = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + cid = "test_cid" + is_conditional = False + is_buy = True + is_market_order = False + + expected_order_mask = basic_composer._order_mask( + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + message = basic_composer.msg_cancel_derivative_order( + market_id=market.id, + sender=sender, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + expected_message = { + "sender": sender, + "marketId": market.id, + "subaccountId": subaccount_id, + "orderHash": order_hash, + "orderMask": expected_order_mask, + "cid": cid, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_subaccount_transfer(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + source_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + destination_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000002" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=amount) + + message = basic_composer.msg_subaccount_transfer( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "sourceSubaccountId": source_subaccount_id, + "destinationSubaccountId": destination_subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_external_transfer(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + source_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + destination_subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=amount) + + message = basic_composer.msg_subaccount_transfer( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "sourceSubaccountId": source_subaccount_id, + "destinationSubaccountId": destination_subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_liquidate_position(self, basic_composer): + market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + order = basic_composer.derivative_order( + market_id=market.id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + margin=Decimal("36.1") * Decimal("100"), + order_type="BUY", + ) + + message = basic_composer.msg_liquidate_position( + sender=sender, + subaccount_id=subaccount_id, + market_id=market.id, + order=order, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "marketId": market.id, + "order": json_format.MessageToDict(message=order, including_default_value_fields=True), + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_emergency_settle_market(self, basic_composer): + market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + + message = basic_composer.msg_emergency_settle_market( + sender=sender, + subaccount_id=subaccount_id, + market_id=market.id, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "marketId": market.id, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_external_transfer(self, basic_composer): + market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + source_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + destination_subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000" + amount = Decimal(100) + + expected_amount = market.margin_to_chain_format(human_readable_value=amount) + + message = basic_composer.msg_increase_position_margin( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + market_id=market.id, + amount=amount, + ) + + expected_message = { + "sender": sender, + "sourceSubaccountId": source_subaccount_id, + "destinationSubaccountId": destination_subaccount_id, + "marketId": market.id, + "amount": f"{expected_amount.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_rewards_opt_out(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + + message = basic_composer.msg_rewards_opt_out( + sender=sender, + ) + + expected_message = { + "sender": sender, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_admin_update_binary_options_market(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + status = "Paused" + settlement_price = Decimal("100.5") + expiration_timestamp = 1630000000 + settlement_timestamp = 1660000000 + + expected_settlement_price = market.price_to_chain_format(human_readable_value=settlement_price) + + message = basic_composer.msg_admin_update_binary_options_market( + sender=sender, + market_id=market.id, + status=status, + settlement_price=settlement_price, + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + ) + + expected_message = { + "sender": sender, + "marketId": market.id, + "settlementPrice": f"{expected_settlement_price.normalize():f}", + "expirationTimestamp": str(expiration_timestamp), + "settlementTimestamp": str(settlement_timestamp), + "status": status, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message diff --git a/tests/test_composer_deprecation_warnings.py b/tests/test_composer_deprecation_warnings.py new file mode 100644 index 00000000..20a86779 --- /dev/null +++ b/tests/test_composer_deprecation_warnings.py @@ -0,0 +1,522 @@ +import warnings +from decimal import Decimal + +import pytest + +from pyinjective.composer import Composer +from pyinjective.core.network import Network +from tests.model_fixtures.markets_fixtures import btc_usdt_perp_market # noqa: F401 +from tests.model_fixtures.markets_fixtures import first_match_bet_market # noqa: F401 +from tests.model_fixtures.markets_fixtures import inj_token # noqa: F401 +from tests.model_fixtures.markets_fixtures import inj_usdt_spot_market # noqa: F401 +from tests.model_fixtures.markets_fixtures import usdt_perp_token # noqa: F401 +from tests.model_fixtures.markets_fixtures import usdt_token # noqa: F401 + + +class TestComposerDeprecationWarnings: + @pytest.fixture + def basic_composer(self, inj_usdt_spot_market, btc_usdt_perp_market, first_match_bet_market): + composer = Composer( + network=Network.devnet().string(), + spot_markets={inj_usdt_spot_market.id: inj_usdt_spot_market}, + derivative_markets={btc_usdt_perp_market.id: btc_usdt_perp_market}, + binary_option_markets={first_match_bet_market.id: first_match_bet_market}, + tokens={ + inj_usdt_spot_market.base_token.symbol: inj_usdt_spot_market.base_token, + inj_usdt_spot_market.quote_token.symbol: inj_usdt_spot_market.quote_token, + btc_usdt_perp_market.quote_token.symbol: btc_usdt_perp_market.quote_token, + }, + ) + + return composer + + def test_msg_deposit_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgDeposit(sender="sender", subaccount_id="subaccount id", amount=1, denom="INJ") + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_deposit instead" + + def test_msg_withdraw_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgWithdraw(sender="sender", subaccount_id="subaccount id", amount=1, denom="USDT") + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_withdraw instead" + + def teste_order_data_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.OrderData( + market_id="market id", + subaccount_id="subaccount id", + order_hash="order hash", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use order_data instead" + + def test_spot_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.SpotOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + is_buy=True, + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use spot_order instead" + + def test_derivative_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.DerivativeOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + is_buy=True, + cid="cid", + leverage=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use derivative_order instead" + + def test_msg_create_spot_limit_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateSpotLimitOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_create_spot_limit_order instead" + ) + + def test_msg_batch_create_spot_limit_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + order = composer.spot_order( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=Decimal(1), + quantity=Decimal(1), + order_type="BUY", + ) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCreateSpotLimitOrders( + sender="sender", + orders=[order], + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_create_spot_limit_orders instead" + ) + + def test_msg_create_spot_market_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateSpotMarketOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + is_buy=True, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_spot_market_order instead" + ) + + def test_msg_cancel_spot_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCancelSpotOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + sender="sender", + subaccount_id="subaccount id", + order_hash="order hash", + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_cancel_spot_order instead" + + def test_msg_batch_cancel_spot_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + orders = [ + composer.order_data( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", + ), + ] + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCancelSpotOrders(sender="sender", data=orders) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_cancel_spot_orders instead" + ) + + def test_msg_batch_update_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchUpdateOrders(sender="sender") + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_batch_update_orders instead" + + def test_msg_privileged_execute_contract_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgPrivilegedExecuteContract( + sender="sender", + contract="contract", + msg="msg", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_privileged_execute_contract instead" + ) + + def test_msg_create_derivative_limit_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateDerivativeLimitOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + leverage=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_derivative_limit_order instead" + ) + + def test_msg_batch_create_derivative_limit_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + order = composer.derivative_order( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=Decimal(1), + quantity=Decimal(1), + margin=Decimal(1), + order_type="BUY", + ) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCreateDerivativeLimitOrders( + sender="sender", + orders=[order], + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_create_derivative_limit_orders instead" + ) + + def test_msg_create_derivative_market_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateDerivativeMarketOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + leverage=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_derivative_market_order instead" + ) + + def test_msg_cancel_derivative_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCancelDerivativeOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + sender="sender", + subaccount_id="subaccount id", + order_hash="order hash", + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_cancel_derivative_order instead" + ) + + def test_msg_batch_cancel_derivative_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + orders = [ + composer.order_data( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", + ), + ] + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCancelDerivativeOrders(sender="sender", data=orders) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_cancel_derivative_orders instead" + ) + + def test_msg_instant_binary_options_market_launch_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgInstantBinaryOptionsMarketLaunch( + sender="sender", + ticker="B2400/INJ", + oracle_symbol="B2400/INJ", + oracle_provider="injective", + oracle_type="Band", + oracle_scale_factor=6, + maker_fee_rate=0.001, + taker_fee_rate=0.001, + expiration_timestamp=1630000000, + settlement_timestamp=1630000000, + quote_denom="inj", + quote_decimals=18, + min_price_tick_size=0.01, + min_quantity_tick_size=0.01, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_instant_binary_options_market_launch instead" + ) + + def test_msg_create_binary_options_limit_order_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgCreateBinaryOptionsLimitOrder( + market_id=market.id, + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + is_buy=True, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_binary_options_limit_order instead" + ) + + def test_msg_create_binary_options_market_order_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgCreateBinaryOptionsMarketOrder( + market_id=market.id, + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + is_buy=True, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_binary_options_market_order instead" + ) + + def test_msg_cancel_binary_options_order_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgCancelBinaryOptionsOrder( + market_id=market.id, + sender="sender", + subaccount_id="subaccount id", + order_hash="order hash", + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_cancel_binary_options_order instead" + ) + + def test_msg_subaccount_transfer_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgSubaccountTransfer( + sender="sender", + source_subaccount_id="source subaccount id", + destination_subaccount_id="destination subaccount id", + amount=1, + denom="INJ", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_subaccount_transfer instead" + + def test_msg_external_transfer_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgExternalTransfer( + sender="sender", + source_subaccount_id="source subaccount id", + destination_subaccount_id="destination subaccount id", + amount=1, + denom="INJ", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_external_transfer instead" + + def test_msg_liquidate_position_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgLiquidatePosition( + sender="sender", + subaccount_id="subaccount id", + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_liquidate_position instead" + + def test_msg_increase_position_margin_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgIncreasePositionMargin( + sender="sender", + source_subaccount_id="source_subaccount id", + destination_subaccount_id="destination_subaccount id", + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + amount=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_increase_position_margin instead" + ) + + def test_msg_rewards_opt_out_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgRewardsOptOut( + sender="sender", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_rewards_opt_out instead" + + def test_msg_admin_update_binary_options_market_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgAdminUpdateBinaryOptionsMarket( + sender="sender", + market_id=market.id, + status="Paused", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_admin_update_binary_options_market instead" + ) diff --git a/tests/test_orderhash.py b/tests/test_orderhash.py index c57b6305..c2940d8d 100644 --- a/tests/test_orderhash.py +++ b/tests/test_orderhash.py @@ -1,3 +1,5 @@ +from decimal import Decimal + from pyinjective import PrivateKey from pyinjective.composer import Composer from pyinjective.core.network import Network @@ -22,23 +24,21 @@ def test_spot_order_hash(self, requests_mock): fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" spot_orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.524, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("0.524"), + quantity=Decimal("0.01"), + order_type="BUY", ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=27.92, - quantity=0.01, - is_buy=False, - is_po=False, + price=Decimal("27.92"), + quantity=Decimal("0.01"), + order_type="SELL", ), ] From 25d3444ea6eb3455e6144975281071128049aade Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 27 Feb 2024 10:50:54 -0300 Subject: [PATCH 20/44] (feat) Adde CodeRabbit configuration file --- .coderabbit.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .coderabbit.yaml diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 00000000..8e534ba3 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,6 @@ +reviews: + auto_review: + base_branches: + - "master" + - "dev" + - "feat/.*" From 4d6ce1b20a77c776ea8dd2d2a64e9b7b460b2e76 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 20 Feb 2024 12:52:10 -0300 Subject: [PATCH 21/44] (feat) Added support for all chain exchange module queries. Included new example scripts for all the queries and unit tests. --- ...drawAddress.py => 1_SetWithdrawAddress.py} | 0 ...Reward.py => 2_WithdrawDelegatorReward.py} | 0 ...on.py => 3_WithdrawValidatorCommission.py} | 0 ...ommunityPool.py => 4_FundCommunityPool.py} | 0 .../1_ValidatorDistributionInfo.py | 0 .../2_ValidatorOutstandingRewards.py | 0 .../{ => query}/3_ValidatorCommission.py | 0 .../{ => query}/4_ValidatorSlashes.py | 0 .../{ => query}/5_DelegationRewards.py | 0 .../{ => query}/6_DelegationTotalRewards.py | 0 .../{ => query}/7_DelegatorValidators.py | 0 .../{ => query}/8_DelegatorWithdrawAddress.py | 0 .../{ => query}/9_CommunityPool.py | 0 .../10_MsgSubaccountTransfer.py} | 0 .../11_MsgBatchUpdateOrders.py} | 0 .../12_MsgRewardsOptOut.py} | 0 .../15_ExternalTransfer.py} | 0 .../16_MsgCreateBinaryOptionsLimitOrder.py} | 0 .../17_MsgCreateBinaryOptionsMarketOrder.py} | 0 .../18_MsgCancelBinaryOptionsOrder.py} | 0 .../19_MsgLiquidatePosition.py} | 0 .../1_MsgDeposit.py} | 0 .../3_MsgCreateSpotLimitOrder.py | 0 .../4_MsgCreateSpotMarketOrder.py | 0 .../{ => exchange}/5_MsgCancelSpotOrder.py | 0 .../6_MsgCreateDerivativeLimitOrder.py | 0 .../7_MsgCreateDerivativeMarketOrder.py | 0 .../8_MsgCancelDerivativeOrder.py | 0 .../9_MsgWithdraw.py} | 0 .../exchange/query/10_SpotMarkets.py | 22 + .../exchange/query/11_SpotMarket.py | 21 + .../exchange/query/12_FullSpotMarkets.py | 23 + .../exchange/query/13_FullSpotMarket.py | 22 + .../exchange/query/14_SpotOrderbook.py | 26 + .../exchange/query/15_TraderSpotOrders.py | 37 + .../query/16_AccountAddressSpotOrders.py | 35 + .../exchange/query/17_SpotOrdersByHashes.py | 38 + .../exchange/query/18_SubaccountOrders.py | 37 + .../query/19_TraderSpotTransientOrders.py | 37 + .../exchange/query/1_SubaccountDeposits.py | 34 + .../exchange/query/20_SpotMidPriceAndTOB.py | 21 + .../query/21_DerivativeMidPriceAndTOB.py | 21 + .../exchange/query/22_DerivativeOrderbook.py | 25 + .../query/23_TraderDerivativeOrders.py | 37 + .../24_AccountAddressDerivativeOrders.py | 35 + .../query/25_DerivativeOrdersByHashes.py | 38 + .../26_TraderDerivativeTransientOrders.py | 37 + .../exchange/query/27_DerivativeMarkets.py | 22 + .../exchange/query/28_DerivativeMarket.py | 21 + .../query/29_DerivativeMarketAddress.py | 21 + .../exchange/query/2_SubaccountDeposit.py | 34 + .../exchange/query/30_SubaccountTradeNonce.py | 36 + .../exchange/query/31_Positions.py | 19 + .../exchange/query/32_SubaccountPositions.py | 36 + .../query/33_SubaccountPossitionInMarket.py | 37 + ...34_SubaccountEffectivePossitionInMarket.py | 37 + .../exchange/query/35_PerpetualMarketInfo.py | 21 + .../query/36_ExpiryFuturesMarketInfo.py | 21 + .../query/37_PerpetualMarketFunding.py | 21 + .../query/38_SubaccountOrderMetadata.py | 36 + .../exchange/query/39_TradeRewardPoints.py | 34 + .../exchange/query/3_ExchangeBalances.py | 18 + .../query/40_PendingTradeRewardPoints.py | 34 + .../query/41_FeeDiscountAccountInfo.py | 34 + .../exchange/query/42_FeeDiscountSchedule.py | 19 + .../exchange/query/43_BalanceMismatches.py | 19 + .../query/44_BalanceWithBalanceHolds.py | 19 + .../query/45_FeeDiscountTierStatistics.py | 19 + .../exchange/query/46_MitoVaultInfos.py | 19 + .../query/47_QueryMarketIDFromVault.py | 19 + .../query/48_HistoricalTradeRecords.py | 21 + .../exchange/query/49_IsOptedOutOfRewards.py | 34 + .../exchange/query/4_AggregateVolume.py | 36 + .../query/50_OptedOutOfRewardsAccounts.py | 19 + .../exchange/query/51_MarketVolatility.py | 30 + .../exchange/query/52_BinaryOptionsMarkets.py | 19 + .../53_TraderDerivativeConditionalOrders.py | 37 + .../54_MarketAtomicExecutionFeeMultiplier.py | 21 + .../exchange/query/5_AggregateVolumes.py | 34 + .../exchange/query/6_AggregateMarketVolume.py | 21 + .../query/7_AggregateMarketVolumes.py | 21 + .../exchange/query/8_DenomDecimal.py | 19 + .../exchange/query/9_DenomDecimals.py | 19 + pyinjective/async_client.py | 393 +++ .../chain/grpc/chain_grpc_exchange_api.py | 572 ++++ .../configurable_exchange_query_servicer.py | 325 +++ .../grpc/test_chain_grpc_exchange_api.py | 2466 +++++++++++++++++ 87 files changed, 5229 insertions(+) rename examples/chain_client/distribution/{10_SetWithdrawAddress.py => 1_SetWithdrawAddress.py} (100%) rename examples/chain_client/distribution/{11_WithdrawDelegatorReward.py => 2_WithdrawDelegatorReward.py} (100%) rename examples/chain_client/distribution/{12_WithdrawValidatorCommission.py => 3_WithdrawValidatorCommission.py} (100%) rename examples/chain_client/distribution/{13_FundCommunityPool.py => 4_FundCommunityPool.py} (100%) rename examples/chain_client/distribution/{ => query}/1_ValidatorDistributionInfo.py (100%) rename examples/chain_client/distribution/{ => query}/2_ValidatorOutstandingRewards.py (100%) rename examples/chain_client/distribution/{ => query}/3_ValidatorCommission.py (100%) rename examples/chain_client/distribution/{ => query}/4_ValidatorSlashes.py (100%) rename examples/chain_client/distribution/{ => query}/5_DelegationRewards.py (100%) rename examples/chain_client/distribution/{ => query}/6_DelegationTotalRewards.py (100%) rename examples/chain_client/distribution/{ => query}/7_DelegatorValidators.py (100%) rename examples/chain_client/distribution/{ => query}/8_DelegatorWithdrawAddress.py (100%) rename examples/chain_client/distribution/{ => query}/9_CommunityPool.py (100%) rename examples/chain_client/{16_MsgSubaccountTransfer.py => exchange/10_MsgSubaccountTransfer.py} (100%) rename examples/chain_client/{17_MsgBatchUpdateOrders.py => exchange/11_MsgBatchUpdateOrders.py} (100%) rename examples/chain_client/{24_MsgRewardsOptOut.py => exchange/12_MsgRewardsOptOut.py} (100%) rename examples/chain_client/{30_ExternalTransfer.py => exchange/15_ExternalTransfer.py} (100%) rename examples/chain_client/{31_MsgCreateBinaryOptionsLimitOrder.py => exchange/16_MsgCreateBinaryOptionsLimitOrder.py} (100%) rename examples/chain_client/{32_MsgCreateBinaryOptionsMarketOrder.py => exchange/17_MsgCreateBinaryOptionsMarketOrder.py} (100%) rename examples/chain_client/{33_MsgCancelBinaryOptionsOrder.py => exchange/18_MsgCancelBinaryOptionsOrder.py} (100%) rename examples/chain_client/{77_MsgLiquidatePosition.py => exchange/19_MsgLiquidatePosition.py} (100%) rename examples/chain_client/{2_MsgDeposit.py => exchange/1_MsgDeposit.py} (100%) rename examples/chain_client/{ => exchange}/3_MsgCreateSpotLimitOrder.py (100%) rename examples/chain_client/{ => exchange}/4_MsgCreateSpotMarketOrder.py (100%) rename examples/chain_client/{ => exchange}/5_MsgCancelSpotOrder.py (100%) rename examples/chain_client/{ => exchange}/6_MsgCreateDerivativeLimitOrder.py (100%) rename examples/chain_client/{ => exchange}/7_MsgCreateDerivativeMarketOrder.py (100%) rename examples/chain_client/{ => exchange}/8_MsgCancelDerivativeOrder.py (100%) rename examples/chain_client/{15_MsgWithdraw.py => exchange/9_MsgWithdraw.py} (100%) create mode 100644 examples/chain_client/exchange/query/10_SpotMarkets.py create mode 100644 examples/chain_client/exchange/query/11_SpotMarket.py create mode 100644 examples/chain_client/exchange/query/12_FullSpotMarkets.py create mode 100644 examples/chain_client/exchange/query/13_FullSpotMarket.py create mode 100644 examples/chain_client/exchange/query/14_SpotOrderbook.py create mode 100644 examples/chain_client/exchange/query/15_TraderSpotOrders.py create mode 100644 examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py create mode 100644 examples/chain_client/exchange/query/17_SpotOrdersByHashes.py create mode 100644 examples/chain_client/exchange/query/18_SubaccountOrders.py create mode 100644 examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py create mode 100644 examples/chain_client/exchange/query/1_SubaccountDeposits.py create mode 100644 examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py create mode 100644 examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py create mode 100644 examples/chain_client/exchange/query/22_DerivativeOrderbook.py create mode 100644 examples/chain_client/exchange/query/23_TraderDerivativeOrders.py create mode 100644 examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py create mode 100644 examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py create mode 100644 examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py create mode 100644 examples/chain_client/exchange/query/27_DerivativeMarkets.py create mode 100644 examples/chain_client/exchange/query/28_DerivativeMarket.py create mode 100644 examples/chain_client/exchange/query/29_DerivativeMarketAddress.py create mode 100644 examples/chain_client/exchange/query/2_SubaccountDeposit.py create mode 100644 examples/chain_client/exchange/query/30_SubaccountTradeNonce.py create mode 100644 examples/chain_client/exchange/query/31_Positions.py create mode 100644 examples/chain_client/exchange/query/32_SubaccountPositions.py create mode 100644 examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py create mode 100644 examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py create mode 100644 examples/chain_client/exchange/query/35_PerpetualMarketInfo.py create mode 100644 examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py create mode 100644 examples/chain_client/exchange/query/37_PerpetualMarketFunding.py create mode 100644 examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py create mode 100644 examples/chain_client/exchange/query/39_TradeRewardPoints.py create mode 100644 examples/chain_client/exchange/query/3_ExchangeBalances.py create mode 100644 examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py create mode 100644 examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py create mode 100644 examples/chain_client/exchange/query/42_FeeDiscountSchedule.py create mode 100644 examples/chain_client/exchange/query/43_BalanceMismatches.py create mode 100644 examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py create mode 100644 examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py create mode 100644 examples/chain_client/exchange/query/46_MitoVaultInfos.py create mode 100644 examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py create mode 100644 examples/chain_client/exchange/query/48_HistoricalTradeRecords.py create mode 100644 examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py create mode 100644 examples/chain_client/exchange/query/4_AggregateVolume.py create mode 100644 examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py create mode 100644 examples/chain_client/exchange/query/51_MarketVolatility.py create mode 100644 examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py create mode 100644 examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py create mode 100644 examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py create mode 100644 examples/chain_client/exchange/query/5_AggregateVolumes.py create mode 100644 examples/chain_client/exchange/query/6_AggregateMarketVolume.py create mode 100644 examples/chain_client/exchange/query/7_AggregateMarketVolumes.py create mode 100644 examples/chain_client/exchange/query/8_DenomDecimal.py create mode 100644 examples/chain_client/exchange/query/9_DenomDecimals.py create mode 100644 pyinjective/client/chain/grpc/chain_grpc_exchange_api.py create mode 100644 tests/client/chain/grpc/configurable_exchange_query_servicer.py create mode 100644 tests/client/chain/grpc/test_chain_grpc_exchange_api.py diff --git a/examples/chain_client/distribution/10_SetWithdrawAddress.py b/examples/chain_client/distribution/1_SetWithdrawAddress.py similarity index 100% rename from examples/chain_client/distribution/10_SetWithdrawAddress.py rename to examples/chain_client/distribution/1_SetWithdrawAddress.py diff --git a/examples/chain_client/distribution/11_WithdrawDelegatorReward.py b/examples/chain_client/distribution/2_WithdrawDelegatorReward.py similarity index 100% rename from examples/chain_client/distribution/11_WithdrawDelegatorReward.py rename to examples/chain_client/distribution/2_WithdrawDelegatorReward.py diff --git a/examples/chain_client/distribution/12_WithdrawValidatorCommission.py b/examples/chain_client/distribution/3_WithdrawValidatorCommission.py similarity index 100% rename from examples/chain_client/distribution/12_WithdrawValidatorCommission.py rename to examples/chain_client/distribution/3_WithdrawValidatorCommission.py diff --git a/examples/chain_client/distribution/13_FundCommunityPool.py b/examples/chain_client/distribution/4_FundCommunityPool.py similarity index 100% rename from examples/chain_client/distribution/13_FundCommunityPool.py rename to examples/chain_client/distribution/4_FundCommunityPool.py diff --git a/examples/chain_client/distribution/1_ValidatorDistributionInfo.py b/examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py similarity index 100% rename from examples/chain_client/distribution/1_ValidatorDistributionInfo.py rename to examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py diff --git a/examples/chain_client/distribution/2_ValidatorOutstandingRewards.py b/examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py similarity index 100% rename from examples/chain_client/distribution/2_ValidatorOutstandingRewards.py rename to examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py diff --git a/examples/chain_client/distribution/3_ValidatorCommission.py b/examples/chain_client/distribution/query/3_ValidatorCommission.py similarity index 100% rename from examples/chain_client/distribution/3_ValidatorCommission.py rename to examples/chain_client/distribution/query/3_ValidatorCommission.py diff --git a/examples/chain_client/distribution/4_ValidatorSlashes.py b/examples/chain_client/distribution/query/4_ValidatorSlashes.py similarity index 100% rename from examples/chain_client/distribution/4_ValidatorSlashes.py rename to examples/chain_client/distribution/query/4_ValidatorSlashes.py diff --git a/examples/chain_client/distribution/5_DelegationRewards.py b/examples/chain_client/distribution/query/5_DelegationRewards.py similarity index 100% rename from examples/chain_client/distribution/5_DelegationRewards.py rename to examples/chain_client/distribution/query/5_DelegationRewards.py diff --git a/examples/chain_client/distribution/6_DelegationTotalRewards.py b/examples/chain_client/distribution/query/6_DelegationTotalRewards.py similarity index 100% rename from examples/chain_client/distribution/6_DelegationTotalRewards.py rename to examples/chain_client/distribution/query/6_DelegationTotalRewards.py diff --git a/examples/chain_client/distribution/7_DelegatorValidators.py b/examples/chain_client/distribution/query/7_DelegatorValidators.py similarity index 100% rename from examples/chain_client/distribution/7_DelegatorValidators.py rename to examples/chain_client/distribution/query/7_DelegatorValidators.py diff --git a/examples/chain_client/distribution/8_DelegatorWithdrawAddress.py b/examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py similarity index 100% rename from examples/chain_client/distribution/8_DelegatorWithdrawAddress.py rename to examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py diff --git a/examples/chain_client/distribution/9_CommunityPool.py b/examples/chain_client/distribution/query/9_CommunityPool.py similarity index 100% rename from examples/chain_client/distribution/9_CommunityPool.py rename to examples/chain_client/distribution/query/9_CommunityPool.py diff --git a/examples/chain_client/16_MsgSubaccountTransfer.py b/examples/chain_client/exchange/10_MsgSubaccountTransfer.py similarity index 100% rename from examples/chain_client/16_MsgSubaccountTransfer.py rename to examples/chain_client/exchange/10_MsgSubaccountTransfer.py diff --git a/examples/chain_client/17_MsgBatchUpdateOrders.py b/examples/chain_client/exchange/11_MsgBatchUpdateOrders.py similarity index 100% rename from examples/chain_client/17_MsgBatchUpdateOrders.py rename to examples/chain_client/exchange/11_MsgBatchUpdateOrders.py diff --git a/examples/chain_client/24_MsgRewardsOptOut.py b/examples/chain_client/exchange/12_MsgRewardsOptOut.py similarity index 100% rename from examples/chain_client/24_MsgRewardsOptOut.py rename to examples/chain_client/exchange/12_MsgRewardsOptOut.py diff --git a/examples/chain_client/30_ExternalTransfer.py b/examples/chain_client/exchange/15_ExternalTransfer.py similarity index 100% rename from examples/chain_client/30_ExternalTransfer.py rename to examples/chain_client/exchange/15_ExternalTransfer.py diff --git a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py similarity index 100% rename from examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py rename to examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py diff --git a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py similarity index 100% rename from examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py rename to examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py diff --git a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py similarity index 100% rename from examples/chain_client/33_MsgCancelBinaryOptionsOrder.py rename to examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py diff --git a/examples/chain_client/77_MsgLiquidatePosition.py b/examples/chain_client/exchange/19_MsgLiquidatePosition.py similarity index 100% rename from examples/chain_client/77_MsgLiquidatePosition.py rename to examples/chain_client/exchange/19_MsgLiquidatePosition.py diff --git a/examples/chain_client/2_MsgDeposit.py b/examples/chain_client/exchange/1_MsgDeposit.py similarity index 100% rename from examples/chain_client/2_MsgDeposit.py rename to examples/chain_client/exchange/1_MsgDeposit.py diff --git a/examples/chain_client/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py similarity index 100% rename from examples/chain_client/3_MsgCreateSpotLimitOrder.py rename to examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py diff --git a/examples/chain_client/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py similarity index 100% rename from examples/chain_client/4_MsgCreateSpotMarketOrder.py rename to examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py diff --git a/examples/chain_client/5_MsgCancelSpotOrder.py b/examples/chain_client/exchange/5_MsgCancelSpotOrder.py similarity index 100% rename from examples/chain_client/5_MsgCancelSpotOrder.py rename to examples/chain_client/exchange/5_MsgCancelSpotOrder.py diff --git a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py similarity index 100% rename from examples/chain_client/6_MsgCreateDerivativeLimitOrder.py rename to examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py diff --git a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py similarity index 100% rename from examples/chain_client/7_MsgCreateDerivativeMarketOrder.py rename to examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py diff --git a/examples/chain_client/8_MsgCancelDerivativeOrder.py b/examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py similarity index 100% rename from examples/chain_client/8_MsgCancelDerivativeOrder.py rename to examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py diff --git a/examples/chain_client/15_MsgWithdraw.py b/examples/chain_client/exchange/9_MsgWithdraw.py similarity index 100% rename from examples/chain_client/15_MsgWithdraw.py rename to examples/chain_client/exchange/9_MsgWithdraw.py diff --git a/examples/chain_client/exchange/query/10_SpotMarkets.py b/examples/chain_client/exchange/query/10_SpotMarkets.py new file mode 100644 index 00000000..4cedc9d7 --- /dev/null +++ b/examples/chain_client/exchange/query/10_SpotMarkets.py @@ -0,0 +1,22 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_markets = await client.fetch_chain_spot_markets( + status="Active", + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(spot_markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/11_SpotMarket.py b/examples/chain_client/exchange/query/11_SpotMarket.py new file mode 100644 index 00000000..0e774edf --- /dev/null +++ b/examples/chain_client/exchange/query/11_SpotMarket.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_market = await client.fetch_chain_spot_market( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(spot_market) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/12_FullSpotMarkets.py b/examples/chain_client/exchange/query/12_FullSpotMarkets.py new file mode 100644 index 00000000..cfefee28 --- /dev/null +++ b/examples/chain_client/exchange/query/12_FullSpotMarkets.py @@ -0,0 +1,23 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_markets = await client.fetch_chain_full_spot_markets( + status="Active", + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + with_mid_price_and_tob=True, + ) + print(spot_markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/13_FullSpotMarket.py b/examples/chain_client/exchange/query/13_FullSpotMarket.py new file mode 100644 index 00000000..6a39269d --- /dev/null +++ b/examples/chain_client/exchange/query/13_FullSpotMarket.py @@ -0,0 +1,22 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_market = await client.fetch_chain_full_spot_market( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + with_mid_price_and_tob=True, + ) + print(spot_market) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/14_SpotOrderbook.py b/examples/chain_client/exchange/query/14_SpotOrderbook.py new file mode 100644 index 00000000..7b5a9aa1 --- /dev/null +++ b/examples/chain_client/exchange/query/14_SpotOrderbook.py @@ -0,0 +1,26 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + pagination = PaginationOption(limit=2) + + orderbook = await client.fetch_chain_spot_orderbook( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + order_side="Buy", + pagination=pagination, + ) + print(orderbook) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/15_TraderSpotOrders.py b/examples/chain_client/exchange/query/15_TraderSpotOrders.py new file mode 100644 index 00000000..0cc96b6f --- /dev/null +++ b/examples/chain_client/exchange/query/15_TraderSpotOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_trader_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py b/examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py new file mode 100644 index 00000000..8e50fa95 --- /dev/null +++ b/examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py @@ -0,0 +1,35 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + orders = await client.fetch_chain_account_address_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + account_address=address.to_acc_bech32(), + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/17_SpotOrdersByHashes.py b/examples/chain_client/exchange/query/17_SpotOrdersByHashes.py new file mode 100644 index 00000000..641eb6f5 --- /dev/null +++ b/examples/chain_client/exchange/query/17_SpotOrdersByHashes.py @@ -0,0 +1,38 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_spot_orders_by_hashes( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id=subaccount_id, + order_hashes=["0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"], + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/18_SubaccountOrders.py b/examples/chain_client/exchange/query/18_SubaccountOrders.py new file mode 100644 index 00000000..4983f827 --- /dev/null +++ b/examples/chain_client/exchange/query/18_SubaccountOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_subaccount_orders( + subaccount_id=subaccount_id, + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py b/examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py new file mode 100644 index 00000000..2b29c2c0 --- /dev/null +++ b/examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_trader_spot_transient_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/1_SubaccountDeposits.py b/examples/chain_client/exchange/query/1_SubaccountDeposits.py new file mode 100644 index 00000000..f9afb8ae --- /dev/null +++ b/examples/chain_client/exchange/query/1_SubaccountDeposits.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + deposits = await client.fetch_subaccount_deposits(subaccount_id=subaccount_id) + print(deposits) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py b/examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py new file mode 100644 index 00000000..35493ffd --- /dev/null +++ b/examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + prices = await client.fetch_spot_mid_price_and_tob( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(prices) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py b/examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py new file mode 100644 index 00000000..5b5c5fff --- /dev/null +++ b/examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + prices = await client.fetch_derivative_mid_price_and_tob( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(prices) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/22_DerivativeOrderbook.py b/examples/chain_client/exchange/query/22_DerivativeOrderbook.py new file mode 100644 index 00000000..465a62b6 --- /dev/null +++ b/examples/chain_client/exchange/query/22_DerivativeOrderbook.py @@ -0,0 +1,25 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + pagination = PaginationOption(limit=2) + + orderbook = await client.fetch_chain_derivative_orderbook( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + pagination=pagination, + ) + print(orderbook) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py b/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py new file mode 100644 index 00000000..61e98ba1 --- /dev/null +++ b/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_trader_spot_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py b/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py new file mode 100644 index 00000000..469c99fb --- /dev/null +++ b/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py @@ -0,0 +1,35 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + orders = await client.fetch_chain_account_address_spot_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + account_address=address.to_acc_bech32(), + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py b/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py new file mode 100644 index 00000000..ea700e6d --- /dev/null +++ b/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py @@ -0,0 +1,38 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_spot_orders_by_hashes( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id=subaccount_id, + order_hashes=["0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"], + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py b/examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py new file mode 100644 index 00000000..c5548d59 --- /dev/null +++ b/examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_trader_derivative_transient_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/27_DerivativeMarkets.py b/examples/chain_client/exchange/query/27_DerivativeMarkets.py new file mode 100644 index 00000000..2f4bbc5a --- /dev/null +++ b/examples/chain_client/exchange/query/27_DerivativeMarkets.py @@ -0,0 +1,22 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + derivative_markets = await client.fetch_chain_derivative_markets( + status="Active", + market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"], + ) + print(derivative_markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/28_DerivativeMarket.py b/examples/chain_client/exchange/query/28_DerivativeMarket.py new file mode 100644 index 00000000..152381f5 --- /dev/null +++ b/examples/chain_client/exchange/query/28_DerivativeMarket.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + derivative_market = await client.fetch_chain_derivative_market( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(derivative_market) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/29_DerivativeMarketAddress.py b/examples/chain_client/exchange/query/29_DerivativeMarketAddress.py new file mode 100644 index 00000000..c2d88805 --- /dev/null +++ b/examples/chain_client/exchange/query/29_DerivativeMarketAddress.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + address = await client.fetch_derivative_market_address( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(address) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/2_SubaccountDeposit.py b/examples/chain_client/exchange/query/2_SubaccountDeposit.py new file mode 100644 index 00000000..5002397d --- /dev/null +++ b/examples/chain_client/exchange/query/2_SubaccountDeposit.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + deposit = await client.fetch_subaccount_deposit(subaccount_id=subaccount_id, denom="inj") + print(deposit) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/30_SubaccountTradeNonce.py b/examples/chain_client/exchange/query/30_SubaccountTradeNonce.py new file mode 100644 index 00000000..ad81aca3 --- /dev/null +++ b/examples/chain_client/exchange/query/30_SubaccountTradeNonce.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + nonce = await client.fetch_subaccount_trade_nonce( + subaccount_id=subaccount_id, + ) + print(nonce) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/31_Positions.py b/examples/chain_client/exchange/query/31_Positions.py new file mode 100644 index 00000000..ae494b6a --- /dev/null +++ b/examples/chain_client/exchange/query/31_Positions.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + positions = await client.fetch_chain_positions() + print(positions) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/32_SubaccountPositions.py b/examples/chain_client/exchange/query/32_SubaccountPositions.py new file mode 100644 index 00000000..000d95b6 --- /dev/null +++ b/examples/chain_client/exchange/query/32_SubaccountPositions.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + positions = await client.fetch_chain_subaccount_positions( + subaccount_id=subaccount_id, + ) + print(positions) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py b/examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py new file mode 100644 index 00000000..4e0f1ddb --- /dev/null +++ b/examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + position = await client.fetch_chain_subaccount_position_in_market( + subaccount_id=subaccount_id, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(position) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py b/examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py new file mode 100644 index 00000000..e729e77c --- /dev/null +++ b/examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + position = await client.fetch_chain_subaccount_effective_position_in_market( + subaccount_id=subaccount_id, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(position) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/35_PerpetualMarketInfo.py b/examples/chain_client/exchange/query/35_PerpetualMarketInfo.py new file mode 100644 index 00000000..ca27f552 --- /dev/null +++ b/examples/chain_client/exchange/query/35_PerpetualMarketInfo.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_info = await client.fetch_chain_perpetual_market_info( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(market_info) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py b/examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py new file mode 100644 index 00000000..4053013c --- /dev/null +++ b/examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_info = await client.fetch_chain_expiry_futures_market_info( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(market_info) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/37_PerpetualMarketFunding.py b/examples/chain_client/exchange/query/37_PerpetualMarketFunding.py new file mode 100644 index 00000000..099c2a0f --- /dev/null +++ b/examples/chain_client/exchange/query/37_PerpetualMarketFunding.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + funding = await client.fetch_chain_perpetual_market_funding( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(funding) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py b/examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py new file mode 100644 index 00000000..f4af9d38 --- /dev/null +++ b/examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + metadata = await client.fetch_subaccount_order_metadata( + subaccount_id=subaccount_id, + ) + print(metadata) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/39_TradeRewardPoints.py b/examples/chain_client/exchange/query/39_TradeRewardPoints.py new file mode 100644 index 00000000..13f08730 --- /dev/null +++ b/examples/chain_client/exchange/query/39_TradeRewardPoints.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + points = await client.fetch_trade_reward_points( + accounts=[address.to_acc_bech32()], + ) + print(points) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/3_ExchangeBalances.py b/examples/chain_client/exchange/query/3_ExchangeBalances.py new file mode 100644 index 00000000..091bf10c --- /dev/null +++ b/examples/chain_client/exchange/query/3_ExchangeBalances.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + # initialize grpc client + client = AsyncClient(network) + + balances = await client.fetch_exchange_balances() + print(balances) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py b/examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py new file mode 100644 index 00000000..fa3e8aa2 --- /dev/null +++ b/examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + points = await client.fetch_pending_trade_reward_points( + accounts=[address.to_acc_bech32()], + ) + print(points) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py b/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py new file mode 100644 index 00000000..15fbb7ce --- /dev/null +++ b/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + fee_discount = await client.fetch_fee_discount_account_info( + account=address.to_acc_bech32(), + ) + print(fee_discount) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py b/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py new file mode 100644 index 00000000..a0ae96cb --- /dev/null +++ b/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + schedule = await client.fetch_fee_discount_schedule() + print(schedule) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/43_BalanceMismatches.py b/examples/chain_client/exchange/query/43_BalanceMismatches.py new file mode 100644 index 00000000..c7f7ca5e --- /dev/null +++ b/examples/chain_client/exchange/query/43_BalanceMismatches.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + mismatches = await client.fetch_balance_mismatches(dust_factor=1) + print(mismatches) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py b/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py new file mode 100644 index 00000000..6587c59a --- /dev/null +++ b/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + balance = await client.fetch_balance_with_balance_holds() + print(balance) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py b/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py new file mode 100644 index 00000000..5671e4ce --- /dev/null +++ b/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + statistics = await client.fetch_fee_discount_tier_statistics() + print(statistics) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/46_MitoVaultInfos.py b/examples/chain_client/exchange/query/46_MitoVaultInfos.py new file mode 100644 index 00000000..3faa5cb9 --- /dev/null +++ b/examples/chain_client/exchange/query/46_MitoVaultInfos.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + infos = await client.fetch_mito_vault_infos() + print(infos) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py b/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py new file mode 100644 index 00000000..e699dbaa --- /dev/null +++ b/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_id = await client.fetch_market_id_from_vault(vault_address="inj1qg5ega6dykkxc307y25pecuufrjkxkag6xhp6y") + print(market_id) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py b/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py new file mode 100644 index 00000000..6b93200f --- /dev/null +++ b/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + records = await client.fetch_historical_trade_records( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + ) + print(records) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py b/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py new file mode 100644 index 00000000..28c0925c --- /dev/null +++ b/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + is_opted_out = await client.fetch_is_opted_out_of_rewards( + account=address.to_acc_bech32(), + ) + print(is_opted_out) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/4_AggregateVolume.py b/examples/chain_client/exchange/query/4_AggregateVolume.py new file mode 100644 index 00000000..35c334a5 --- /dev/null +++ b/examples/chain_client/exchange/query/4_AggregateVolume.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + + subaccount_id = address.get_subaccount_id(index=0) + + volume = await client.fetch_aggregate_volume(account=address.to_acc_bech32()) + print(volume) + + volume = await client.fetch_aggregate_volume(account=subaccount_id) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py b/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py new file mode 100644 index 00000000..9940f799 --- /dev/null +++ b/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + opted_out = await client.fetch_opted_out_of_rewards_accounts() + print(opted_out) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/51_MarketVolatility.py b/examples/chain_client/exchange/query/51_MarketVolatility.py new file mode 100644 index 00000000..3173ca39 --- /dev/null +++ b/examples/chain_client/exchange/query/51_MarketVolatility.py @@ -0,0 +1,30 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + trade_grouping_sec = 10 + max_age = 0 + include_raw_history = True + include_metadata = True + volatility = await client.fetch_market_volatility( + market_id=market_id, + trade_grouping_sec=trade_grouping_sec, + max_age=max_age, + include_raw_history=include_raw_history, + include_metadata=include_metadata, + ) + print(volatility) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py b/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py new file mode 100644 index 00000000..4448a4ec --- /dev/null +++ b/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + markets = await client.fetch_chain_binary_options_markets(status="Active") + print(markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py b/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py new file mode 100644 index 00000000..fd65e68f --- /dev/null +++ b/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_trader_derivative_conditional_orders( + subaccount_id=subaccount_id, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py b/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py new file mode 100644 index 00000000..328028d3 --- /dev/null +++ b/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + multiplier = await client.fetch_market_atomic_execution_fee_multiplier( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(multiplier) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/5_AggregateVolumes.py b/examples/chain_client/exchange/query/5_AggregateVolumes.py new file mode 100644 index 00000000..6effe4be --- /dev/null +++ b/examples/chain_client/exchange/query/5_AggregateVolumes.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + + volume = await client.fetch_aggregate_volumes( + accounts=[address.to_acc_bech32()], + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/6_AggregateMarketVolume.py b/examples/chain_client/exchange/query/6_AggregateMarketVolume.py new file mode 100644 index 00000000..b3262d82 --- /dev/null +++ b/examples/chain_client/exchange/query/6_AggregateMarketVolume.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + + volume = await client.fetch_aggregate_market_volume(market_id=market_id) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/7_AggregateMarketVolumes.py b/examples/chain_client/exchange/query/7_AggregateMarketVolumes.py new file mode 100644 index 00000000..23dfa0ec --- /dev/null +++ b/examples/chain_client/exchange/query/7_AggregateMarketVolumes.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + volume = await client.fetch_aggregate_market_volumes( + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/8_DenomDecimal.py b/examples/chain_client/exchange/query/8_DenomDecimal.py new file mode 100644 index 00000000..2079f5e8 --- /dev/null +++ b/examples/chain_client/exchange/query/8_DenomDecimal.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + deposits = await client.fetch_denom_decimal(denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5") + print(deposits) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/9_DenomDecimals.py b/examples/chain_client/exchange/query/9_DenomDecimals.py new file mode 100644 index 00000000..d96df30b --- /dev/null +++ b/examples/chain_client/exchange/query/9_DenomDecimals.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + deposits = await client.fetch_denom_decimals(denoms=["inj", "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"]) + print(deposits) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index dea12f12..0af37da0 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -13,6 +13,7 @@ from pyinjective.client.chain.grpc.chain_grpc_authz_api import ChainGrpcAuthZApi from pyinjective.client.chain.grpc.chain_grpc_bank_api import ChainGrpcBankApi from pyinjective.client.chain.grpc.chain_grpc_distribution_api import ChainGrpcDistributionApi +from pyinjective.client.chain.grpc.chain_grpc_exchange_api import ChainGrpcExchangeApi from pyinjective.client.chain.grpc.chain_grpc_token_factory_api import ChainGrpcTokenFactoryApi from pyinjective.client.chain.grpc.chain_grpc_wasm_api import ChainGrpcWasmApi from pyinjective.client.chain.grpc_stream.chain_grpc_chain_stream import ChainGrpcChainStream @@ -185,6 +186,12 @@ def __init__( metadata_query_provider=self._chain_cookie_metadata_requestor ), ) + self.chain_exchange_api = ChainGrpcExchangeApi( + channel=self.chain_channel, + metadata_provider=lambda: self.network.chain_metadata( + metadata_query_provider=self._chain_cookie_metadata_requestor + ), + ) self.token_factory_api = ChainGrpcTokenFactoryApi( channel=self.chain_channel, metadata_provider=lambda: self.network.chain_metadata( @@ -639,6 +646,392 @@ async def fetch_delegator_withdraw_address( async def fetch_community_pool(self) -> Dict[str, Any]: return await self.distribution_api.fetch_community_pool() + # Exchange module + + async def fetch_subaccount_deposits( + self, + subaccount_id: Optional[str] = None, + subaccount_trader: Optional[str] = None, + subaccount_nonce: Optional[int] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_deposits( + subaccount_id=subaccount_id, + subaccount_trader=subaccount_trader, + subaccount_nonce=subaccount_nonce, + ) + + async def fetch_subaccount_deposit( + self, + subaccount_id: str, + denom: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_deposit( + subaccount_id=subaccount_id, + denom=denom, + ) + + async def fetch_exchange_balances(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_exchange_balances() + + async def fetch_aggregate_volume(self, account: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_volume(account=account) + + async def fetch_aggregate_volumes( + self, + accounts: Optional[List[str]] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_volumes( + accounts=accounts, + market_ids=market_ids, + ) + + async def fetch_aggregate_market_volume( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_market_volume( + market_id=market_id, + ) + + async def fetch_aggregate_market_volumes( + self, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_market_volumes( + market_ids=market_ids, + ) + + async def fetch_denom_decimal(self, denom: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_denom_decimal(denom=denom) + + async def fetch_denom_decimals(self, denoms: Optional[List[str]] = None) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_denom_decimals(denoms=denoms) + + async def fetch_chain_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_markets( + status=status, + market_ids=market_ids, + ) + + async def fetch_chain_spot_market( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_market( + market_id=market_id, + ) + + async def fetch_chain_full_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_full_spot_markets( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + + async def fetch_chain_full_spot_market( + self, + market_id: str, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_full_spot_market( + market_id=market_id, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + + async def fetch_chain_spot_orderbook( + self, + market_id: str, + order_side: Optional[str] = None, + limit_cumulative_notional: Optional[str] = None, + limit_cumulative_quantity: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + # Order side could be "Side_Unspecified", "Buy", "Sell" + return await self.chain_exchange_api.fetch_spot_orderbook( + market_id=market_id, + order_side=order_side, + limit_cumulative_notional=limit_cumulative_notional, + limit_cumulative_quantity=limit_cumulative_quantity, + pagination=pagination, + ) + + async def fetch_chain_trader_spot_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_spot_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_chain_account_address_spot_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_account_address_spot_orders( + market_id=market_id, + account_address=account_address, + ) + + async def fetch_chain_spot_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_orders_by_hashes( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + + async def fetch_chain_subaccount_orders( + self, + subaccount_id: str, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_orders( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_chain_trader_spot_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_spot_transient_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_spot_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_mid_price_and_tob( + market_id=market_id, + ) + + async def fetch_derivative_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_mid_price_and_tob( + market_id=market_id, + ) + + async def fetch_chain_derivative_orderbook( + self, + market_id: str, + limit_cumulative_notional: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_orderbook( + market_id=market_id, + limit_cumulative_notional=limit_cumulative_notional, + pagination=pagination, + ) + + async def fetch_chain_trader_derivative_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_derivative_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_chain_account_address_derivative_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_account_address_derivative_orders( + market_id=market_id, + account_address=account_address, + ) + + async def fetch_chain_derivative_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_orders_by_hashes( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + + async def fetch_chain_trader_derivative_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_derivative_transient_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_chain_derivative_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_markets( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + + async def fetch_chain_derivative_market( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_market( + market_id=market_id, + ) + + async def fetch_derivative_market_address(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_market_address(market_id=market_id) + + async def fetch_subaccount_trade_nonce(self, subaccount_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_trade_nonce(subaccount_id=subaccount_id) + + async def fetch_chain_positions(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_positions() + + async def fetch_chain_subaccount_positions(self, subaccount_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_positions(subaccount_id=subaccount_id) + + async def fetch_chain_subaccount_position_in_market(self, subaccount_id: str, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_chain_subaccount_effective_position_in_market( + self, subaccount_id: str, market_id: str + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_effective_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_chain_perpetual_market_info(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_perpetual_market_info(market_id=market_id) + + async def fetch_chain_expiry_futures_market_info(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_expiry_futures_market_info(market_id=market_id) + + async def fetch_chain_perpetual_market_funding(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_perpetual_market_funding(market_id=market_id) + + async def fetch_subaccount_order_metadata(self, subaccount_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_order_metadata(subaccount_id=subaccount_id) + + async def fetch_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trade_reward_points( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + + async def fetch_pending_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_pending_trade_reward_points( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + + async def fetch_fee_discount_account_info(self, account: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_fee_discount_account_info(account=account) + + async def fetch_fee_discount_schedule(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_fee_discount_schedule() + + async def fetch_balance_mismatches(self, dust_factor: int) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_balance_mismatches(dust_factor=dust_factor) + + async def fetch_balance_with_balance_holds(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_balance_with_balance_holds() + + async def fetch_fee_discount_tier_statistics(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_fee_discount_tier_statistics() + + async def fetch_mito_vault_infos(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_mito_vault_infos() + + async def fetch_market_id_from_vault(self, vault_address: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_market_id_from_vault(vault_address=vault_address) + + async def fetch_historical_trade_records(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_historical_trade_records(market_id=market_id) + + async def fetch_is_opted_out_of_rewards(self, account: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_is_opted_out_of_rewards(account=account) + + async def fetch_opted_out_of_rewards_accounts(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_opted_out_of_rewards_accounts() + + async def fetch_market_volatility( + self, + market_id: str, + trade_grouping_sec: Optional[int] = None, + max_age: Optional[int] = None, + include_raw_history: Optional[bool] = None, + include_metadata: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_market_volatility( + market_id=market_id, + trade_grouping_sec=trade_grouping_sec, + max_age=max_age, + include_raw_history=include_raw_history, + include_metadata=include_metadata, + ) + + async def fetch_chain_binary_options_markets(self, status: Optional[str] = None) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_binary_options_markets(status=status) + + async def fetch_trader_derivative_conditional_orders( + self, + subaccount_id: Optional[str] = None, + market_id: Optional[str] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_derivative_conditional_orders( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_market_atomic_execution_fee_multiplier( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_market_atomic_execution_fee_multiplier( + market_id=market_id, + ) + # Injective Exchange client methods # Auction RPC diff --git a/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py b/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py new file mode 100644 index 00000000..217c0d34 --- /dev/null +++ b/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py @@ -0,0 +1,572 @@ +from typing import Any, Callable, Dict, List, Optional + +from grpc.aio import Channel + +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.proto.injective.exchange.v1beta1 import ( + query_pb2 as exchange_query_pb, + query_pb2_grpc as exchange_query_grpc, +) +from pyinjective.utils.grpc_api_request_assistant import GrpcApiRequestAssistant + + +class ChainGrpcExchangeApi: + def __init__(self, channel: Channel, metadata_provider: Callable): + self._stub = exchange_query_grpc.QueryStub(channel) + self._assistant = GrpcApiRequestAssistant(metadata_provider=metadata_provider) + + async def fetch_exchange_params(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryExchangeParamsRequest() + response = await self._execute_call(call=self._stub.QueryExchangeParams, request=request) + + return response + + async def fetch_subaccount_deposits( + self, + subaccount_id: Optional[str] = None, + subaccount_trader: Optional[str] = None, + subaccount_nonce: Optional[int] = None, + ) -> Dict[str, Any]: + subaccount = None + if subaccount_trader is not None or subaccount_nonce is not None: + subaccount = exchange_query_pb.Subaccount( + trader=subaccount_trader, + subaccount_nonce=subaccount_nonce, + ) + + request = exchange_query_pb.QuerySubaccountDepositsRequest(subaccount_id=subaccount_id, subaccount=subaccount) + response = await self._execute_call(call=self._stub.SubaccountDeposits, request=request) + + return response + + async def fetch_subaccount_deposit( + self, + subaccount_id: str, + denom: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountDepositRequest( + subaccount_id=subaccount_id, + denom=denom, + ) + response = await self._execute_call(call=self._stub.SubaccountDeposit, request=request) + + return response + + async def fetch_exchange_balances(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryExchangeBalancesRequest() + response = await self._execute_call(call=self._stub.ExchangeBalances, request=request) + + return response + + async def fetch_aggregate_volume(self, account: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateVolumeRequest(account=account) + response = await self._execute_call(call=self._stub.AggregateVolume, request=request) + + return response + + async def fetch_aggregate_volumes( + self, + accounts: Optional[List[str]] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateVolumesRequest(accounts=accounts, market_ids=market_ids) + response = await self._execute_call(call=self._stub.AggregateVolumes, request=request) + + return response + + async def fetch_aggregate_market_volume(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateMarketVolumeRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.AggregateMarketVolume, request=request) + + return response + + async def fetch_aggregate_market_volumes(self, market_ids: Optional[List[str]] = None) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateMarketVolumesRequest(market_ids=market_ids) + response = await self._execute_call(call=self._stub.AggregateMarketVolumes, request=request) + + return response + + async def fetch_denom_decimal(self, denom: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryDenomDecimalRequest(denom=denom) + response = await self._execute_call(call=self._stub.DenomDecimal, request=request) + + return response + + async def fetch_denom_decimals(self, denoms: Optional[List[str]] = None) -> Dict[str, Any]: + request = exchange_query_pb.QueryDenomDecimalsRequest(denoms=denoms) + response = await self._execute_call(call=self._stub.DenomDecimals, request=request) + + return response + + async def fetch_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotMarketsRequest( + status=status, + market_ids=market_ids, + ) + response = await self._execute_call(call=self._stub.SpotMarkets, request=request) + + return response + + async def fetch_spot_market(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotMarketRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.SpotMarket, request=request) + + return response + + async def fetch_full_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFullSpotMarketsRequest( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + response = await self._execute_call(call=self._stub.FullSpotMarkets, request=request) + + return response + + async def fetch_full_spot_market( + self, + market_id: str, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFullSpotMarketRequest( + market_id=market_id, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + response = await self._execute_call(call=self._stub.FullSpotMarket, request=request) + + return response + + async def fetch_spot_orderbook( + self, + market_id: str, + order_side: Optional[str] = None, + limit_cumulative_notional: Optional[str] = None, + limit_cumulative_quantity: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + limit = None + if pagination is not None: + limit = pagination.limit + request = exchange_query_pb.QuerySpotOrderbookRequest( + market_id=market_id, + order_side=order_side, + limit=limit, + limit_cumulative_notional=limit_cumulative_notional, + limit_cumulative_quantity=limit_cumulative_quantity, + ) + response = await self._execute_call(call=self._stub.SpotOrderbook, request=request) + + return response + + async def fetch_trader_spot_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderSpotOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderSpotOrders, request=request) + + return response + + async def fetch_account_address_spot_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryAccountAddressSpotOrdersRequest( + market_id=market_id, + account_address=account_address, + ) + response = await self._execute_call(call=self._stub.AccountAddressSpotOrders, request=request) + + return response + + async def fetch_spot_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotOrdersByHashesRequest( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + response = await self._execute_call(call=self._stub.SpotOrdersByHashes, request=request) + + return response + + async def fetch_subaccount_orders( + self, + subaccount_id: str, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountOrdersRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SubaccountOrders, request=request) + + return response + + async def fetch_trader_spot_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderSpotOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderSpotTransientOrders, request=request) + + return response + + async def fetch_spot_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotMidPriceAndTOBRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SpotMidPriceAndTOB, request=request) + + return response + + async def fetch_derivative_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMidPriceAndTOBRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.DerivativeMidPriceAndTOB, request=request) + + return response + + async def fetch_derivative_orderbook( + self, + market_id: str, + limit_cumulative_notional: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + limit = None + if pagination is not None: + limit = pagination.limit + request = exchange_query_pb.QueryDerivativeOrderbookRequest( + market_id=market_id, + limit=limit, + limit_cumulative_notional=limit_cumulative_notional, + ) + response = await self._execute_call(call=self._stub.DerivativeOrderbook, request=request) + + return response + + async def fetch_trader_derivative_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderDerivativeOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderDerivativeOrders, request=request) + + return response + + async def fetch_account_address_derivative_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryAccountAddressDerivativeOrdersRequest( + market_id=market_id, + account_address=account_address, + ) + response = await self._execute_call(call=self._stub.AccountAddressDerivativeOrders, request=request) + + return response + + async def fetch_derivative_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeOrdersByHashesRequest( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + response = await self._execute_call(call=self._stub.DerivativeOrdersByHashes, request=request) + + return response + + async def fetch_trader_derivative_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderDerivativeOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderDerivativeTransientOrders, request=request) + + return response + + async def fetch_derivative_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMarketsRequest( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + response = await self._execute_call(call=self._stub.DerivativeMarkets, request=request) + + return response + + async def fetch_derivative_market( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMarketRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.DerivativeMarket, request=request) + + return response + + async def fetch_derivative_market_address( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMarketAddressRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.DerivativeMarketAddress, request=request) + + return response + + async def fetch_subaccount_trade_nonce(self, subaccount_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountTradeNonceRequest(subaccount_id=subaccount_id) + response = await self._execute_call(call=self._stub.SubaccountTradeNonce, request=request) + + return response + + async def fetch_positions(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryPositionsRequest() + response = await self._execute_call(call=self._stub.Positions, request=request) + + return response + + async def fetch_subaccount_positions(self, subaccount_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountPositionsRequest(subaccount_id=subaccount_id) + response = await self._execute_call(call=self._stub.SubaccountPositions, request=request) + + return response + + async def fetch_subaccount_position_in_market(self, subaccount_id: str, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountPositionInMarketRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SubaccountPositionInMarket, request=request) + + return response + + async def fetch_subaccount_effective_position_in_market(self, subaccount_id: str, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountEffectivePositionInMarketRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SubaccountEffectivePositionInMarket, request=request) + + return response + + async def fetch_perpetual_market_info(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryPerpetualMarketInfoRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.PerpetualMarketInfo, request=request) + + return response + + async def fetch_expiry_futures_market_info(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryExpiryFuturesMarketInfoRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.ExpiryFuturesMarketInfo, request=request) + + return response + + async def fetch_perpetual_market_funding(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryPerpetualMarketFundingRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.PerpetualMarketFunding, request=request) + + return response + + async def fetch_subaccount_order_metadata(self, subaccount_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountOrderMetadataRequest(subaccount_id=subaccount_id) + response = await self._execute_call(call=self._stub.SubaccountOrderMetadata, request=request) + + return response + + async def fetch_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTradeRewardPointsRequest( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + response = await self._execute_call(call=self._stub.TradeRewardPoints, request=request) + + return response + + async def fetch_pending_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTradeRewardPointsRequest( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + response = await self._execute_call(call=self._stub.PendingTradeRewardPoints, request=request) + + return response + + async def fetch_fee_discount_account_info( + self, + account: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFeeDiscountAccountInfoRequest(account=account) + response = await self._execute_call(call=self._stub.FeeDiscountAccountInfo, request=request) + + return response + + async def fetch_fee_discount_schedule(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryFeeDiscountScheduleRequest() + response = await self._execute_call(call=self._stub.FeeDiscountSchedule, request=request) + + return response + + async def fetch_balance_mismatches(self, dust_factor: int) -> Dict[str, Any]: + request = exchange_query_pb.QueryBalanceMismatchesRequest(dust_factor=dust_factor) + response = await self._execute_call(call=self._stub.BalanceMismatches, request=request) + + return response + + async def fetch_balance_with_balance_holds(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryBalanceWithBalanceHoldsRequest() + response = await self._execute_call(call=self._stub.BalanceWithBalanceHolds, request=request) + + return response + + async def fetch_fee_discount_tier_statistics(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryFeeDiscountTierStatisticsRequest() + response = await self._execute_call(call=self._stub.FeeDiscountTierStatistics, request=request) + + return response + + async def fetch_mito_vault_infos(self) -> Dict[str, Any]: + request = exchange_query_pb.MitoVaultInfosRequest() + response = await self._execute_call(call=self._stub.MitoVaultInfos, request=request) + + return response + + async def fetch_market_id_from_vault(self, vault_address: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryMarketIDFromVaultRequest(vault_address=vault_address) + response = await self._execute_call(call=self._stub.QueryMarketIDFromVault, request=request) + + return response + + async def fetch_historical_trade_records(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryHistoricalTradeRecordsRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.HistoricalTradeRecords, request=request) + + return response + + async def fetch_is_opted_out_of_rewards(self, account: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryIsOptedOutOfRewardsRequest(account=account) + response = await self._execute_call(call=self._stub.IsOptedOutOfRewards, request=request) + + return response + + async def fetch_opted_out_of_rewards_accounts(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryOptedOutOfRewardsAccountsRequest() + response = await self._execute_call(call=self._stub.OptedOutOfRewardsAccounts, request=request) + + return response + + async def fetch_market_volatility( + self, + market_id: str, + trade_grouping_sec: Optional[int] = None, + max_age: Optional[int] = None, + include_raw_history: Optional[bool] = None, + include_metadata: Optional[bool] = None, + ) -> Dict[str, Any]: + trade_history_options = exchange_query_pb.TradeHistoryOptions() + if trade_grouping_sec is not None: + trade_history_options.trade_grouping_sec = trade_grouping_sec + if max_age is not None: + trade_history_options.max_age = max_age + if include_raw_history is not None: + trade_history_options.include_raw_history = include_raw_history + if include_metadata is not None: + trade_history_options.include_metadata = include_metadata + request = exchange_query_pb.QueryMarketVolatilityRequest( + market_id=market_id, trade_history_options=trade_history_options + ) + response = await self._execute_call(call=self._stub.MarketVolatility, request=request) + + return response + + async def fetch_binary_options_markets(self, status: Optional[str] = None) -> Dict[str, Any]: + request = exchange_query_pb.QueryBinaryMarketsRequest(status=status) + response = await self._execute_call(call=self._stub.BinaryOptionsMarkets, request=request) + + return response + + async def fetch_trader_derivative_conditional_orders( + self, + subaccount_id: Optional[str] = None, + market_id: Optional[str] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderDerivativeConditionalOrdersRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.TraderDerivativeConditionalOrders, request=request) + + return response + + async def fetch_market_atomic_execution_fee_multiplier( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryMarketAtomicExecutionFeeMultiplierRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.MarketAtomicExecutionFeeMultiplier, request=request) + + return response + + async def _execute_call(self, call: Callable, request) -> Dict[str, Any]: + return await self._assistant.execute_call(call=call, request=request) diff --git a/tests/client/chain/grpc/configurable_exchange_query_servicer.py b/tests/client/chain/grpc/configurable_exchange_query_servicer.py new file mode 100644 index 00000000..267b08ce --- /dev/null +++ b/tests/client/chain/grpc/configurable_exchange_query_servicer.py @@ -0,0 +1,325 @@ +from collections import deque + +from pyinjective.proto.injective.exchange.v1beta1 import ( + query_pb2 as exchange_query_pb, + query_pb2_grpc as exchange_query_grpc, +) + + +class ConfigurableExchangeQueryServicer(exchange_query_grpc.QueryServicer): + def __init__(self): + super().__init__() + self.exchange_params = deque() + self.subaccount_deposits_responses = deque() + self.subaccount_deposit_responses = deque() + self.exchange_balances_responses = deque() + self.aggregate_volume_responses = deque() + self.aggregate_volumes_responses = deque() + self.aggregate_market_volume_responses = deque() + self.aggregate_market_volumes_responses = deque() + self.denom_decimal_responses = deque() + self.denom_decimals_responses = deque() + self.spot_markets_responses = deque() + self.spot_market_responses = deque() + self.full_spot_markets_responses = deque() + self.full_spot_market_responses = deque() + self.spot_orderbook_responses = deque() + self.trader_spot_orders_responses = deque() + self.account_address_spot_orders_responses = deque() + self.spot_orders_by_hashes_responses = deque() + self.subaccount_orders_responses = deque() + self.trader_spot_transient_orders_responses = deque() + self.spot_mid_price_and_tob_responses = deque() + self.derivative_mid_price_and_tob_responses = deque() + self.derivative_orderbook_responses = deque() + self.trader_derivative_orders_responses = deque() + self.account_address_derivative_orders_responses = deque() + self.derivative_orders_by_hashes_responses = deque() + self.trader_derivative_transient_orders_responses = deque() + self.derivative_markets_responses = deque() + self.derivative_market_responses = deque() + self.derivative_market_address_responses = deque() + self.subaccount_trade_nonce_responses = deque() + self.positions_responses = deque() + self.subaccount_positions_responses = deque() + self.subaccount_position_in_market_responses = deque() + self.subaccount_effective_position_in_market_responses = deque() + self.perpetual_market_info_responses = deque() + self.expiry_futures_market_info_responses = deque() + self.perpetual_market_funding_responses = deque() + self.subaccount_order_metadata_responses = deque() + self.trade_reward_points_responses = deque() + self.pending_trade_reward_points_responses = deque() + self.fee_discount_account_info_responses = deque() + self.fee_discount_schedule_responses = deque() + self.balance_mismatches_responses = deque() + self.balance_with_balance_holds_responses = deque() + self.fee_discount_tier_statistics_responses = deque() + self.mito_vault_infos_responses = deque() + self.market_id_from_vault_responses = deque() + self.historical_trade_records_responses = deque() + self.is_opted_out_of_rewards_responses = deque() + self.opted_out_of_rewards_accounts_responses = deque() + self.market_volatility_responses = deque() + self.binary_options_markets_responses = deque() + self.trader_derivative_conditional_orders_responses = deque() + self.market_atomic_execution_fee_multiplier_responses = deque() + + async def QueryExchangeParams( + self, request: exchange_query_pb.QueryExchangeParamsRequest, context=None, metadata=None + ): + return self.exchange_params.pop() + + async def SubaccountDeposits( + self, request: exchange_query_pb.QuerySubaccountDepositsRequest, context=None, metadata=None + ): + return self.subaccount_deposits_responses.pop() + + async def SubaccountDeposit( + self, request: exchange_query_pb.QuerySubaccountDepositRequest, context=None, metadata=None + ): + return self.subaccount_deposit_responses.pop() + + async def ExchangeBalances( + self, request: exchange_query_pb.QueryExchangeBalancesRequest, context=None, metadata=None + ): + return self.exchange_balances_responses.pop() + + async def AggregateVolume( + self, request: exchange_query_pb.QueryAggregateVolumeRequest, context=None, metadata=None + ): + return self.aggregate_volume_responses.pop() + + async def AggregateVolumes( + self, request: exchange_query_pb.QueryAggregateVolumesRequest, context=None, metadata=None + ): + return self.aggregate_volumes_responses.pop() + + async def AggregateMarketVolume( + self, request: exchange_query_pb.QueryAggregateMarketVolumeRequest, context=None, metadata=None + ): + return self.aggregate_market_volume_responses.pop() + + async def AggregateMarketVolumes( + self, request: exchange_query_pb.QueryAggregateMarketVolumesRequest, context=None, metadata=None + ): + return self.aggregate_market_volumes_responses.pop() + + async def DenomDecimal(self, request: exchange_query_pb.QueryDenomDecimalRequest, context=None, metadata=None): + return self.denom_decimal_responses.pop() + + async def DenomDecimals(self, request: exchange_query_pb.QueryDenomDecimalsRequest, context=None, metadata=None): + return self.denom_decimals_responses.pop() + + async def SpotMarkets(self, request: exchange_query_pb.QuerySpotMarketsRequest, context=None, metadata=None): + return self.spot_markets_responses.pop() + + async def SpotMarket(self, request: exchange_query_pb.QuerySpotMarketRequest, context=None, metadata=None): + return self.spot_market_responses.pop() + + async def FullSpotMarkets( + self, request: exchange_query_pb.QueryFullSpotMarketsRequest, context=None, metadata=None + ): + return self.full_spot_markets_responses.pop() + + async def FullSpotMarket(self, request: exchange_query_pb.QueryFullSpotMarketRequest, context=None, metadata=None): + return self.full_spot_market_responses.pop() + + async def SpotOrderbook(self, request: exchange_query_pb.QuerySpotOrderbookRequest, context=None, metadata=None): + return self.spot_orderbook_responses.pop() + + async def TraderSpotOrders( + self, request: exchange_query_pb.QueryTraderSpotOrdersRequest, context=None, metadata=None + ): + return self.trader_spot_orders_responses.pop() + + async def AccountAddressSpotOrders( + self, request: exchange_query_pb.QueryAccountAddressSpotOrdersRequest, context=None, metadata=None + ): + return self.account_address_spot_orders_responses.pop() + + async def SpotOrdersByHashes( + self, request: exchange_query_pb.QuerySpotOrdersByHashesRequest, context=None, metadata=None + ): + return self.spot_orders_by_hashes_responses.pop() + + async def SubaccountOrders( + self, request: exchange_query_pb.QuerySubaccountOrdersRequest, context=None, metadata=None + ): + return self.subaccount_orders_responses.pop() + + async def TraderSpotTransientOrders( + self, request: exchange_query_pb.QueryTraderSpotOrdersRequest, context=None, metadata=None + ): + return self.trader_spot_transient_orders_responses.pop() + + async def SpotMidPriceAndTOB( + self, request: exchange_query_pb.QuerySpotMidPriceAndTOBRequest, context=None, metadata=None + ): + return self.spot_mid_price_and_tob_responses.pop() + + async def DerivativeMidPriceAndTOB( + self, request: exchange_query_pb.QueryDerivativeMidPriceAndTOBRequest, context=None, metadata=None + ): + return self.derivative_mid_price_and_tob_responses.pop() + + async def DerivativeOrderbook( + self, request: exchange_query_pb.QueryDerivativeOrderbookRequest, context=None, metadata=None + ): + return self.derivative_orderbook_responses.pop() + + async def TraderDerivativeOrders( + self, request: exchange_query_pb.QueryTraderDerivativeOrdersRequest, context=None, metadata=None + ): + return self.trader_derivative_orders_responses.pop() + + async def AccountAddressDerivativeOrders( + self, request: exchange_query_pb.QueryAccountAddressDerivativeOrdersRequest, context=None, metadata=None + ): + return self.account_address_derivative_orders_responses.pop() + + async def DerivativeOrdersByHashes( + self, request: exchange_query_pb.QueryDerivativeOrdersByHashesRequest, context=None, metadata=None + ): + return self.derivative_orders_by_hashes_responses.pop() + + async def TraderDerivativeTransientOrders( + self, request: exchange_query_pb.QueryTraderDerivativeOrdersRequest, context=None, metadata=None + ): + return self.trader_derivative_transient_orders_responses.pop() + + async def DerivativeMarkets( + self, request: exchange_query_pb.QueryDerivativeMarketsRequest, context=None, metadata=None + ): + return self.derivative_markets_responses.pop() + + async def DerivativeMarket( + self, request: exchange_query_pb.QueryDerivativeMarketRequest, context=None, metadata=None + ): + return self.derivative_market_responses.pop() + + async def DerivativeMarketAddress( + self, request: exchange_query_pb.QueryDerivativeMarketAddressRequest, context=None, metadata=None + ): + return self.derivative_market_address_responses.pop() + + async def SubaccountTradeNonce( + self, request: exchange_query_pb.QuerySubaccountTradeNonceRequest, context=None, metadata=None + ): + return self.subaccount_trade_nonce_responses.pop() + + async def Positions(self, request: exchange_query_pb.QueryPositionsRequest, context=None, metadata=None): + return self.positions_responses.pop() + + async def SubaccountPositions( + self, request: exchange_query_pb.QuerySubaccountPositionsRequest, context=None, metadata=None + ): + return self.subaccount_positions_responses.pop() + + async def SubaccountPositionInMarket( + self, request: exchange_query_pb.QuerySubaccountPositionInMarketRequest, context=None, metadata=None + ): + return self.subaccount_position_in_market_responses.pop() + + async def SubaccountEffectivePositionInMarket( + self, request: exchange_query_pb.QuerySubaccountEffectivePositionInMarketRequest, context=None, metadata=None + ): + return self.subaccount_effective_position_in_market_responses.pop() + + async def PerpetualMarketInfo( + self, request: exchange_query_pb.QueryPerpetualMarketInfoRequest, context=None, metadata=None + ): + return self.perpetual_market_info_responses.pop() + + async def ExpiryFuturesMarketInfo( + self, request: exchange_query_pb.QueryExpiryFuturesMarketInfoRequest, context=None, metadata=None + ): + return self.expiry_futures_market_info_responses.pop() + + async def PerpetualMarketFunding( + self, request: exchange_query_pb.QueryPerpetualMarketFundingRequest, context=None, metadata=None + ): + return self.perpetual_market_funding_responses.pop() + + async def SubaccountOrderMetadata( + self, request: exchange_query_pb.QuerySubaccountOrderMetadataRequest, context=None, metadata=None + ): + return self.subaccount_order_metadata_responses.pop() + + async def TradeRewardPoints( + self, request: exchange_query_pb.QueryTradeRewardPointsRequest, context=None, metadata=None + ): + return self.trade_reward_points_responses.pop() + + async def PendingTradeRewardPoints( + self, request: exchange_query_pb.QueryTradeRewardPointsRequest, context=None, metadata=None + ): + return self.pending_trade_reward_points_responses.pop() + + async def FeeDiscountAccountInfo( + self, request: exchange_query_pb.QueryFeeDiscountAccountInfoRequest, context=None, metadata=None + ): + return self.fee_discount_account_info_responses.pop() + + async def FeeDiscountSchedule( + self, request: exchange_query_pb.QueryFeeDiscountScheduleRequest, context=None, metadata=None + ): + return self.fee_discount_schedule_responses.pop() + + async def BalanceMismatches( + self, request: exchange_query_pb.QueryBalanceMismatchesRequest, context=None, metadata=None + ): + return self.balance_mismatches_responses.pop() + + async def BalanceWithBalanceHolds( + self, request: exchange_query_pb.QueryBalanceWithBalanceHoldsRequest, context=None, metadata=None + ): + return self.balance_with_balance_holds_responses.pop() + + async def FeeDiscountTierStatistics( + self, request: exchange_query_pb.QueryFeeDiscountTierStatisticsRequest, context=None, metadata=None + ): + return self.fee_discount_tier_statistics_responses.pop() + + async def MitoVaultInfos(self, request: exchange_query_pb.MitoVaultInfosRequest, context=None, metadata=None): + return self.mito_vault_infos_responses.pop() + + async def QueryMarketIDFromVault( + self, request: exchange_query_pb.QueryMarketIDFromVaultRequest, context=None, metadata=None + ): + return self.market_id_from_vault_responses.pop() + + async def HistoricalTradeRecords( + self, request: exchange_query_pb.QueryHistoricalTradeRecordsRequest, context=None, metadata=None + ): + return self.historical_trade_records_responses.pop() + + async def IsOptedOutOfRewards( + self, request: exchange_query_pb.QueryIsOptedOutOfRewardsRequest, context=None, metadata=None + ): + return self.is_opted_out_of_rewards_responses.pop() + + async def OptedOutOfRewardsAccounts( + self, request: exchange_query_pb.QueryOptedOutOfRewardsAccountsRequest, context=None, metadata=None + ): + return self.opted_out_of_rewards_accounts_responses.pop() + + async def MarketVolatility( + self, request: exchange_query_pb.QueryMarketVolatilityRequest, context=None, metadata=None + ): + return self.market_volatility_responses.pop() + + async def BinaryOptionsMarkets( + self, request: exchange_query_pb.QueryBinaryMarketsRequest, context=None, metadata=None + ): + return self.binary_options_markets_responses.pop() + + async def TraderDerivativeConditionalOrders( + self, request: exchange_query_pb.QueryTraderDerivativeConditionalOrdersRequest, context=None, metadata=None + ): + return self.trader_derivative_conditional_orders_responses.pop() + + async def MarketAtomicExecutionFeeMultiplier( + self, request: exchange_query_pb.QueryMarketAtomicExecutionFeeMultiplierRequest, context=None, metadata=None + ): + return self.market_atomic_execution_fee_multiplier_responses.pop() diff --git a/tests/client/chain/grpc/test_chain_grpc_exchange_api.py b/tests/client/chain/grpc/test_chain_grpc_exchange_api.py new file mode 100644 index 00000000..54393a94 --- /dev/null +++ b/tests/client/chain/grpc/test_chain_grpc_exchange_api.py @@ -0,0 +1,2466 @@ +import base64 + +import grpc +import pytest + +from pyinjective.client.chain.grpc.chain_grpc_exchange_api import ChainGrpcExchangeApi +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network +from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as coin_pb +from pyinjective.proto.injective.exchange.v1beta1 import ( + exchange_pb2 as exchange_pb, + genesis_pb2 as genesis_pb, + query_pb2 as exchange_query_pb, +) +from pyinjective.proto.injective.oracle.v1beta1 import oracle_pb2 as oracle_pb +from tests.client.chain.grpc.configurable_exchange_query_servicer import ConfigurableExchangeQueryServicer + + +@pytest.fixture +def exchange_servicer(): + return ConfigurableExchangeQueryServicer() + + +class TestChainGrpcBankApi: + @pytest.mark.asyncio + async def test_fetch_exchange_params( + self, + exchange_servicer, + ): + spot_market_instant_listing_fee = coin_pb.Coin(denom="inj", amount="10000000000000000000") + derivative_market_instant_listing_fee = coin_pb.Coin(denom="inj", amount="2000000000000000000000") + binary_options_market_instant_listing_fee = coin_pb.Coin(denom="inj", amount="30000000000000000000") + params = exchange_pb.Params( + spot_market_instant_listing_fee=spot_market_instant_listing_fee, + derivative_market_instant_listing_fee=derivative_market_instant_listing_fee, + default_spot_maker_fee_rate="-0.000100000000000000", + default_spot_taker_fee_rate="0.001000000000000000", + default_derivative_maker_fee_rate="-0.000100000000000000", + default_derivative_taker_fee_rate="0.001000000000000000", + default_initial_margin_ratio="0.050000000000000000", + default_maintenance_margin_ratio="0.020000000000000000", + default_funding_interval=3600, + funding_multiple=4600, + relayer_fee_share_rate="0.400000000000000000", + default_hourly_funding_rate_cap="0.000625000000000000", + default_hourly_interest_rate="0.000004166660000000", + max_derivative_order_side_count=20, + inj_reward_staked_requirement_threshold="25000000000000000000", + trading_rewards_vesting_duration=1209600, + liquidator_reward_share_rate="0.050000000000000000", + binary_options_market_instant_listing_fee=binary_options_market_instant_listing_fee, + atomic_market_order_access_level=2, + spot_atomic_market_order_fee_multiplier="2.000000000000000000", + derivative_atomic_market_order_fee_multiplier="2.000000000000000000", + binary_options_atomic_market_order_fee_multiplier="2.000000000000000000", + minimal_protocol_fee_rate="0.000010000000000000", + is_instant_derivative_market_launch_enabled=False, + post_only_mode_height_threshold=57078000, + ) + exchange_servicer.exchange_params.append(exchange_query_pb.QueryExchangeParamsResponse(params=params)) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + module_params = await api.fetch_exchange_params() + expected_params = { + "params": { + "spotMarketInstantListingFee": { + "amount": spot_market_instant_listing_fee.amount, + "denom": spot_market_instant_listing_fee.denom, + }, + "derivativeMarketInstantListingFee": { + "amount": derivative_market_instant_listing_fee.amount, + "denom": derivative_market_instant_listing_fee.denom, + }, + "defaultSpotMakerFeeRate": params.default_spot_maker_fee_rate, + "defaultSpotTakerFeeRate": params.default_spot_taker_fee_rate, + "defaultDerivativeMakerFeeRate": params.default_derivative_maker_fee_rate, + "defaultDerivativeTakerFeeRate": params.default_derivative_taker_fee_rate, + "defaultInitialMarginRatio": params.default_initial_margin_ratio, + "defaultMaintenanceMarginRatio": params.default_maintenance_margin_ratio, + "defaultFundingInterval": str(params.default_funding_interval), + "fundingMultiple": str(params.funding_multiple), + "relayerFeeShareRate": params.relayer_fee_share_rate, + "defaultHourlyFundingRateCap": params.default_hourly_funding_rate_cap, + "defaultHourlyInterestRate": params.default_hourly_interest_rate, + "maxDerivativeOrderSideCount": params.max_derivative_order_side_count, + "injRewardStakedRequirementThreshold": params.inj_reward_staked_requirement_threshold, + "tradingRewardsVestingDuration": str(params.trading_rewards_vesting_duration), + "liquidatorRewardShareRate": "0.050000000000000000", + "binaryOptionsMarketInstantListingFee": { + "amount": binary_options_market_instant_listing_fee.amount, + "denom": binary_options_market_instant_listing_fee.denom, + }, + "atomicMarketOrderAccessLevel": exchange_pb.AtomicMarketOrderAccessLevel.Name( + params.atomic_market_order_access_level + ), + "spotAtomicMarketOrderFeeMultiplier": params.spot_atomic_market_order_fee_multiplier, + "derivativeAtomicMarketOrderFeeMultiplier": params.derivative_atomic_market_order_fee_multiplier, + "binaryOptionsAtomicMarketOrderFeeMultiplier": params.binary_options_atomic_market_order_fee_multiplier, + "minimalProtocolFeeRate": params.minimal_protocol_fee_rate, + "isInstantDerivativeMarketLaunchEnabled": params.is_instant_derivative_market_launch_enabled, + "postOnlyModeHeightThreshold": str(params.post_only_mode_height_threshold), + } + } + + assert module_params == expected_params + + @pytest.mark.asyncio + async def test_fetch_subaccount_deposits( + self, + exchange_servicer, + ): + deposit_denom = "inj" + deposit = exchange_pb.Deposit( + available_balance="1000000000000000000", + total_balance="2000000000000000000", + ) + exchange_servicer.subaccount_deposits_responses.append( + exchange_query_pb.QuerySubaccountDepositsResponse(deposits={deposit_denom: deposit}) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + deposits = await api.fetch_subaccount_deposits( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + subaccount_trader="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7", + subaccount_nonce=1, + ) + expected_deposits = { + "deposits": { + deposit_denom: { + "availableBalance": deposit.available_balance, + "totalBalance": deposit.total_balance, + }, + } + } + + assert deposits == expected_deposits + + @pytest.mark.asyncio + async def test_fetch_subaccount_deposit( + self, + exchange_servicer, + ): + deposit = exchange_pb.Deposit( + available_balance="1000000000000000000", + total_balance="2000000000000000000", + ) + exchange_servicer.subaccount_deposit_responses.append( + exchange_query_pb.QuerySubaccountDepositResponse(deposits=deposit) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + deposit_response = await api.fetch_subaccount_deposit( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="inj", + ) + expected_deposit = { + "deposits": { + "availableBalance": deposit.available_balance, + "totalBalance": deposit.total_balance, + } + } + + assert deposit_response == expected_deposit + + @pytest.mark.asyncio + async def test_fetch_exchange_balances( + self, + exchange_servicer, + ): + deposit = exchange_pb.Deposit( + available_balance="1000000000000000000", + total_balance="2000000000000000000", + ) + balance = genesis_pb.Balance( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="inj", + deposits=deposit, + ) + exchange_servicer.exchange_balances_responses.append( + exchange_query_pb.QueryExchangeBalancesResponse(balances=[balance]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + balances_response = await api.fetch_exchange_balances() + expected_balances = { + "balances": [ + { + "subaccountId": balance.subaccount_id, + "denom": balance.denom, + "deposits": { + "availableBalance": deposit.available_balance, + "totalBalance": deposit.total_balance, + }, + }, + ] + } + + assert balances_response == expected_balances + + @pytest.mark.asyncio + async def test_fetch_aggregate_volume( + self, + exchange_servicer, + ): + volume = exchange_pb.VolumeRecord( + maker_volume="1000000000000000000", + taker_volume="2000000000000000000", + ) + market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=volume, + ) + exchange_servicer.aggregate_volume_responses.append( + exchange_query_pb.QueryAggregateVolumeResponse( + aggregate_volumes=[market_volume], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_volume(account="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r") + expected_volume = { + "aggregateVolumes": [ + { + "marketId": market_volume.market_id, + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + }, + }, + ] + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_aggregate_volumes( + self, + exchange_servicer, + ): + acc_volume = exchange_pb.VolumeRecord( + maker_volume="1000000000000000000", + taker_volume="2000000000000000000", + ) + account_market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=acc_volume, + ) + account_volume = exchange_pb.AggregateAccountVolumeRecord( + account="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + market_volumes=[account_market_volume], + ) + volume = exchange_pb.VolumeRecord( + maker_volume="3000000000000000000", + taker_volume="4000000000000000000", + ) + market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=volume, + ) + exchange_servicer.aggregate_volumes_responses.append( + exchange_query_pb.QueryAggregateVolumesResponse( + aggregate_account_volumes=[account_volume], + aggregate_market_volumes=[market_volume], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_volumes( + accounts=[account_volume.account], + market_ids=[account_market_volume.market_id], + ) + expected_volume = { + "aggregateAccountVolumes": [ + { + "account": account_volume.account, + "marketVolumes": [ + { + "marketId": account_market_volume.market_id, + "volume": { + "makerVolume": acc_volume.maker_volume, + "takerVolume": acc_volume.taker_volume, + }, + }, + ], + }, + ], + "aggregateMarketVolumes": [ + { + "marketId": market_volume.market_id, + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + }, + }, + ], + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_aggregate_market_volume( + self, + exchange_servicer, + ): + volume = exchange_pb.VolumeRecord( + maker_volume="1000000000000000000", + taker_volume="2000000000000000000", + ) + exchange_servicer.aggregate_market_volume_responses.append( + exchange_query_pb.QueryAggregateMarketVolumeResponse( + volume=volume, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_market_volume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + ) + expected_volume = { + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + } + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_aggregate_market_volumes( + self, + exchange_servicer, + ): + volume = exchange_pb.VolumeRecord( + maker_volume="3000000000000000000", + taker_volume="4000000000000000000", + ) + market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=volume, + ) + exchange_servicer.aggregate_market_volumes_responses.append( + exchange_query_pb.QueryAggregateMarketVolumesResponse( + volumes=[market_volume], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_market_volumes( + market_ids=[market_volume.market_id], + ) + expected_volume = { + "volumes": [ + { + "marketId": market_volume.market_id, + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + }, + }, + ], + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_denom_decimal( + self, + exchange_servicer, + ): + decimal = 18 + exchange_servicer.denom_decimal_responses.append( + exchange_query_pb.QueryDenomDecimalResponse( + decimal=decimal, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + denom_decimal = await api.fetch_denom_decimal(denom="inj") + expected_decimal = {"decimal": str(decimal)} + + assert denom_decimal == expected_decimal + + @pytest.mark.asyncio + async def test_fetch_denom_decimals( + self, + exchange_servicer, + ): + denom_decimal = exchange_pb.DenomDecimals( + denom="inj", + decimals=18, + ) + exchange_servicer.denom_decimals_responses.append( + exchange_query_pb.QueryDenomDecimalsResponse( + denom_decimals=[denom_decimal], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + denom_decimals = await api.fetch_denom_decimals(denoms=[denom_decimal.denom]) + expected_decimals = { + "denomDecimals": [ + { + "denom": denom_decimal.denom, + "decimals": str(denom_decimal.decimals), + } + ] + } + + assert denom_decimals == expected_decimals + + @pytest.mark.asyncio + async def test_fetch_spot_markets( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + exchange_servicer.spot_markets_responses.append( + exchange_query_pb.QuerySpotMarketsResponse( + markets=[market], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + markets = await api.fetch_spot_markets( + status=status_string, + market_ids=[market.market_id], + ) + expected_markets = { + "markets": [ + { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + } + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_spot_market( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + exchange_servicer.spot_market_responses.append( + exchange_query_pb.QuerySpotMarketResponse( + market=market, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + response_market = await api.fetch_spot_market( + market_id=market.market_id, + ) + expected_market = { + "market": { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": exchange_pb.MarketStatus.Name(market.status), + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + } + } + + assert response_market == expected_market + + @pytest.mark.asyncio + async def test_fetch_full_spot_markets( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullSpotMarket( + market=market, + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.full_spot_markets_responses.append( + exchange_query_pb.QueryFullSpotMarketsResponse( + markets=[full_market], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + markets = await api.fetch_full_spot_markets( + status=status_string, + market_ids=[market.market_id], + with_mid_price_and_tob=True, + ) + expected_markets = { + "markets": [ + { + "market": { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_full_spot_market( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullSpotMarket( + market=market, + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.full_spot_market_responses.append( + exchange_query_pb.QueryFullSpotMarketResponse( + market=full_market, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + market_response = await api.fetch_full_spot_market( + market_id=market.market_id, + with_mid_price_and_tob=True, + ) + expected_market = { + "market": { + "market": { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + } + + assert market_response == expected_market + + @pytest.mark.asyncio + async def test_fetch_spot_orderbook( + self, + exchange_servicer, + ): + buy_price_level = exchange_pb.Level( + p="1000000000000000000", + q="1000000000000000", + ) + sell_price_level = exchange_pb.Level( + p="2000000000000000000", + q="2000000000000000", + ) + exchange_servicer.spot_orderbook_responses.append( + exchange_query_pb.QuerySpotOrderbookResponse( + buys_price_level=[buy_price_level], + sells_price_level=[sell_price_level], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orderbook = await api.fetch_spot_orderbook( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + order_side="Side_Unspecified", + limit_cumulative_notional="1000000000000000000", + limit_cumulative_quantity="1000000000000000", + pagination=PaginationOption(limit=100), + ) + expected_orderbook = { + "buysPriceLevel": [ + { + "p": buy_price_level.p, + "q": buy_price_level.q, + } + ], + "sellsPriceLevel": [ + { + "p": sell_price_level.p, + "q": sell_price_level.q, + } + ], + } + + assert orderbook == expected_orderbook + + @pytest.mark.asyncio + async def test_fetch_trader_spot_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_spot_orders_responses.append( + exchange_query_pb.QueryTraderSpotOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_account_address_spot_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.account_address_spot_orders_responses.append( + exchange_query_pb.QueryAccountAddressSpotOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_account_address_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + account_address="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_spot_orders_by_hashes( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.spot_orders_by_hashes_responses.append( + exchange_query_pb.QuerySpotOrdersByHashesResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_spot_orders_by_hashes( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + order_hashes=[order.order_hash], + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_subaccount_orders( + self, + exchange_servicer, + ): + buy_subaccount_order = exchange_pb.SubaccountOrder( + price="1000000000000000000", + quantity="1000000000000000", + isReduceOnly=False, + ) + buy_order = exchange_pb.SubaccountOrderData( + order=buy_subaccount_order, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849".encode(), + ) + sell_subaccount_order = exchange_pb.SubaccountOrder( + price="2000000000000000000", + quantity="2000000000000000", + isReduceOnly=False, + ) + sell_order = exchange_pb.SubaccountOrderData( + order=sell_subaccount_order, + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2".encode(), + ) + exchange_servicer.subaccount_orders_responses.append( + exchange_query_pb.QuerySubaccountOrdersResponse( + buy_orders=[buy_order], + sell_orders=[sell_order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_subaccount_orders( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + expected_orders = { + "buyOrders": [ + { + "order": { + "price": buy_subaccount_order.price, + "quantity": buy_subaccount_order.quantity, + "isReduceOnly": buy_subaccount_order.isReduceOnly, + }, + "orderHash": base64.b64encode(buy_order.order_hash).decode(), + } + ], + "sellOrders": [ + { + "order": { + "price": sell_subaccount_order.price, + "quantity": sell_subaccount_order.quantity, + "isReduceOnly": sell_subaccount_order.isReduceOnly, + }, + "orderHash": base64.b64encode(sell_order.order_hash).decode(), + } + ], + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_trader_spot_transient_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_spot_transient_orders_responses.append( + exchange_query_pb.QueryTraderSpotOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_spot_transient_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_spot_mid_price_and_tob( + self, + exchange_servicer, + ): + response = exchange_query_pb.QuerySpotMidPriceAndTOBResponse( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + exchange_servicer.spot_mid_price_and_tob_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + prices = await api.fetch_spot_mid_price_and_tob( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + expected_prices = { + "midPrice": response.mid_price, + "bestBuyPrice": response.best_buy_price, + "bestSellPrice": response.best_sell_price, + } + + assert prices == expected_prices + + @pytest.mark.asyncio + async def test_fetch_derivative_mid_price_and_tob( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryDerivativeMidPriceAndTOBResponse( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + exchange_servicer.derivative_mid_price_and_tob_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + prices = await api.fetch_derivative_mid_price_and_tob( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + expected_prices = { + "midPrice": response.mid_price, + "bestBuyPrice": response.best_buy_price, + "bestSellPrice": response.best_sell_price, + } + + assert prices == expected_prices + + @pytest.mark.asyncio + async def test_fetch_derivative_orderbook( + self, + exchange_servicer, + ): + buy_price_level = exchange_pb.Level( + p="1000000000000000000", + q="1000000000000000", + ) + sell_price_level = exchange_pb.Level( + p="2000000000000000000", + q="2000000000000000", + ) + exchange_servicer.derivative_orderbook_responses.append( + exchange_query_pb.QueryDerivativeOrderbookResponse( + buys_price_level=[buy_price_level], + sells_price_level=[sell_price_level], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orderbook = await api.fetch_derivative_orderbook( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + limit_cumulative_notional="1000000000000000000", + pagination=PaginationOption(limit=100), + ) + expected_orderbook = { + "buysPriceLevel": [ + { + "p": buy_price_level.p, + "q": buy_price_level.q, + } + ], + "sellsPriceLevel": [ + { + "p": sell_price_level.p, + "q": sell_price_level.q, + } + ], + } + + assert orderbook == expected_orderbook + + @pytest.mark.asyncio + async def test_fetch_trader_derivative_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_derivative_orders_responses.append( + exchange_query_pb.QueryTraderDerivativeOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_derivative_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_account_address_derivative_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.account_address_derivative_orders_responses.append( + exchange_query_pb.QueryAccountAddressDerivativeOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_account_address_derivative_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + account_address="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_derivative_orders_by_hashes( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.derivative_orders_by_hashes_responses.append( + exchange_query_pb.QueryDerivativeOrdersByHashesResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_derivative_orders_by_hashes( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + order_hashes=[order.order_hash], + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_trader_derivative_transient_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_derivative_transient_orders_responses.append( + exchange_query_pb.QueryTraderDerivativeOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_derivative_transient_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_derivative_markets( + self, + exchange_servicer, + ): + market = exchange_pb.DerivativeMarket( + ticker="20250608/USDT", + oracle_base="0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3", + oracle_quote="0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588", + oracle_type=9, + oracle_scale_factor=6, + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + initial_margin_ratio="50000000000000000", + maintenance_margin_ratio="20000000000000000", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="400000000000000000", + isPerpetual=True, + status=1, + min_price_tick_size="100000000000000000000", + min_quantity_tick_size="1000000000000000", + ) + market_info = exchange_pb.PerpetualMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + hourly_funding_rate_cap="625000000000000", + hourly_interest_rate="4166660000000", + next_funding_timestamp=1708099200, + funding_interval=3600, + ) + funding_info = exchange_pb.PerpetualMarketFunding( + cumulative_funding="-107853477278881692857461", + cumulative_price="0", + last_timestamp=1708099200, + ) + perpetual_info = exchange_query_pb.PerpetualMarketState( + market_info=market_info, + funding_info=funding_info, + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullDerivativeMarket( + market=market, + perpetual_info=perpetual_info, + mark_price="33803835513327368963000000", + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.derivative_markets_responses.append( + exchange_query_pb.QueryDerivativeMarketsResponse( + markets=[full_market], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + markets = await api.fetch_derivative_markets( + status=status_string, + market_ids=[market.market_id], + ) + expected_markets = { + "markets": [ + { + "market": { + "ticker": market.ticker, + "oracleBase": market.oracle_base, + "oracleQuote": market.oracle_quote, + "oracleType": oracle_pb.OracleType.Name(market.oracle_type), + "oracleScaleFactor": market.oracle_scale_factor, + "quoteDenom": market.quote_denom, + "marketId": market.market_id, + "initialMarginRatio": market.initial_margin_ratio, + "maintenanceMarginRatio": market.maintenance_margin_ratio, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "isPerpetual": market.isPerpetual, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "perpetualInfo": { + "marketInfo": { + "marketId": market_info.market_id, + "hourlyFundingRateCap": market_info.hourly_funding_rate_cap, + "hourlyInterestRate": market_info.hourly_interest_rate, + "nextFundingTimestamp": str(market_info.next_funding_timestamp), + "fundingInterval": str(market_info.funding_interval), + }, + "fundingInfo": { + "cumulativeFunding": funding_info.cumulative_funding, + "cumulativePrice": funding_info.cumulative_price, + "lastTimestamp": str(funding_info.last_timestamp), + }, + }, + "markPrice": full_market.mark_price, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_derivative_market( + self, + exchange_servicer, + ): + market = exchange_pb.DerivativeMarket( + ticker="INJ/USDT PERP", + oracle_base="0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3", + oracle_quote="0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588", + oracle_type=9, + oracle_scale_factor=6, + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + initial_margin_ratio="50000000000000000", + maintenance_margin_ratio="20000000000000000", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="400000000000000000", + isPerpetual=True, + status=1, + min_price_tick_size="100000000000000000000", + min_quantity_tick_size="1000000000000000", + ) + market_info = exchange_pb.PerpetualMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + hourly_funding_rate_cap="625000000000000", + hourly_interest_rate="4166660000000", + next_funding_timestamp=1708099200, + funding_interval=3600, + ) + funding_info = exchange_pb.PerpetualMarketFunding( + cumulative_funding="-107853477278881692857461", + cumulative_price="0", + last_timestamp=1708099200, + ) + perpetual_info = exchange_query_pb.PerpetualMarketState( + market_info=market_info, + funding_info=funding_info, + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullDerivativeMarket( + market=market, + perpetual_info=perpetual_info, + mark_price="33803835513327368963000000", + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.derivative_market_responses.append( + exchange_query_pb.QueryDerivativeMarketResponse( + market=full_market, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + market_response = await api.fetch_derivative_market( + market_id=market.market_id, + ) + expected_market = { + "market": { + "market": { + "ticker": market.ticker, + "oracleBase": market.oracle_base, + "oracleQuote": market.oracle_quote, + "oracleType": oracle_pb.OracleType.Name(market.oracle_type), + "oracleScaleFactor": market.oracle_scale_factor, + "quoteDenom": market.quote_denom, + "marketId": market.market_id, + "initialMarginRatio": market.initial_margin_ratio, + "maintenanceMarginRatio": market.maintenance_margin_ratio, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "isPerpetual": market.isPerpetual, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "perpetualInfo": { + "marketInfo": { + "marketId": market_info.market_id, + "hourlyFundingRateCap": market_info.hourly_funding_rate_cap, + "hourlyInterestRate": market_info.hourly_interest_rate, + "nextFundingTimestamp": str(market_info.next_funding_timestamp), + "fundingInterval": str(market_info.funding_interval), + }, + "fundingInfo": { + "cumulativeFunding": funding_info.cumulative_funding, + "cumulativePrice": funding_info.cumulative_price, + "lastTimestamp": str(funding_info.last_timestamp), + }, + }, + "markPrice": full_market.mark_price, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + } + + assert market_response == expected_market + + @pytest.mark.asyncio + async def test_fetch_derivative_market_address( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryDerivativeMarketAddressResponse( + address="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9", + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + ) + exchange_servicer.derivative_market_address_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + address = await api.fetch_derivative_market_address( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + expected_address = { + "address": response.address, + "subaccountId": response.subaccount_id, + } + + assert address == expected_address + + @pytest.mark.asyncio + async def test_fetch_subaccount_trade_nonce( + self, + exchange_servicer, + ): + response = exchange_query_pb.QuerySubaccountTradeNonceResponse(nonce=1234567879) + exchange_servicer.subaccount_trade_nonce_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + nonce = await api.fetch_subaccount_trade_nonce( + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + ) + expected_nonce = { + "nonce": response.nonce, + } + + assert nonce == expected_nonce + + @pytest.mark.asyncio + async def test_fetch_positions( + self, + exchange_servicer, + ): + position = exchange_pb.Position( + isLong=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + margin="2000000000000000000000000000000000", + cumulative_funding_entry="4000000", + ) + derivative_position = genesis_pb.DerivativePosition( + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + position=position, + ) + exchange_servicer.positions_responses.append( + exchange_query_pb.QueryPositionsResponse(state=[derivative_position]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + positions = await api.fetch_positions() + expected_positions = { + "state": [ + { + "subaccountId": derivative_position.subaccount_id, + "marketId": derivative_position.market_id, + "position": { + "isLong": position.isLong, + "quantity": position.quantity, + "entryPrice": position.entry_price, + "margin": position.margin, + "cumulativeFundingEntry": position.cumulative_funding_entry, + }, + }, + ], + } + + assert positions == expected_positions + + @pytest.mark.asyncio + async def test_fetch_subaccount_positions( + self, + exchange_servicer, + ): + position = exchange_pb.Position( + isLong=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + margin="2000000000000000000000000000000000", + cumulative_funding_entry="4000000", + ) + derivative_position = genesis_pb.DerivativePosition( + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + position=position, + ) + exchange_servicer.subaccount_positions_responses.append( + exchange_query_pb.QuerySubaccountPositionsResponse(state=[derivative_position]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + positions = await api.fetch_subaccount_positions(subaccount_id=derivative_position.subaccount_id) + expected_positions = { + "state": [ + { + "subaccountId": derivative_position.subaccount_id, + "marketId": derivative_position.market_id, + "position": { + "isLong": position.isLong, + "quantity": position.quantity, + "entryPrice": position.entry_price, + "margin": position.margin, + "cumulativeFundingEntry": position.cumulative_funding_entry, + }, + }, + ], + } + + assert positions == expected_positions + + @pytest.mark.asyncio + async def test_fetch_subaccount_position_in_market( + self, + exchange_servicer, + ): + subaccount_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000" + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + position = exchange_pb.Position( + isLong=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + margin="2000000000000000000000000000000000", + cumulative_funding_entry="4000000", + ) + exchange_servicer.subaccount_position_in_market_responses.append( + exchange_query_pb.QuerySubaccountPositionInMarketResponse(state=position) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + position_response = await api.fetch_subaccount_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + expected_position = { + "state": { + "isLong": position.isLong, + "quantity": position.quantity, + "entryPrice": position.entry_price, + "margin": position.margin, + "cumulativeFundingEntry": position.cumulative_funding_entry, + }, + } + + assert position_response == expected_position + + @pytest.mark.asyncio + async def test_fetch_subaccount_effective_position_in_market( + self, + exchange_servicer, + ): + subaccount_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000" + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + + effective_position = exchange_query_pb.EffectivePosition( + is_long=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + effective_margin="2000000000000000000000000000000000", + ) + exchange_servicer.subaccount_effective_position_in_market_responses.append( + exchange_query_pb.QuerySubaccountEffectivePositionInMarketResponse(state=effective_position) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + position_response = await api.fetch_subaccount_effective_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + expected_position = { + "state": { + "isLong": effective_position.is_long, + "quantity": effective_position.quantity, + "entryPrice": effective_position.entry_price, + "effectiveMargin": effective_position.effective_margin, + }, + } + + assert position_response == expected_position + + @pytest.mark.asyncio + async def test_fetch_perpetual_market_info( + self, + exchange_servicer, + ): + perpetual_market_info = exchange_pb.PerpetualMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + hourly_funding_rate_cap="625000000000000", + hourly_interest_rate="4166660000000", + next_funding_timestamp=1708099200, + funding_interval=3600, + ) + exchange_servicer.perpetual_market_info_responses.append( + exchange_query_pb.QueryPerpetualMarketInfoResponse(info=perpetual_market_info) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + market_info = await api.fetch_perpetual_market_info(market_id=perpetual_market_info.market_id) + expected_market_info = { + "info": { + "marketId": perpetual_market_info.market_id, + "hourlyFundingRateCap": perpetual_market_info.hourly_funding_rate_cap, + "hourlyInterestRate": perpetual_market_info.hourly_interest_rate, + "nextFundingTimestamp": str(perpetual_market_info.next_funding_timestamp), + "fundingInterval": str(perpetual_market_info.funding_interval), + } + } + + assert market_info == expected_market_info + + @pytest.mark.asyncio + async def test_fetch_expiry_futures_market_info( + self, + exchange_servicer, + ): + expiry_futures_market_info = exchange_pb.ExpiryFuturesMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + expiration_timestamp=1708099200, + twap_start_timestamp=1705566200, + expiration_twap_start_price_cumulative="1000000000000000000", + settlement_price="2000000000000000000", + ) + exchange_servicer.expiry_futures_market_info_responses.append( + exchange_query_pb.QueryExpiryFuturesMarketInfoResponse(info=expiry_futures_market_info) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + market_info = await api.fetch_expiry_futures_market_info(market_id=expiry_futures_market_info.market_id) + expected_market_info = { + "info": { + "marketId": expiry_futures_market_info.market_id, + "expirationTimestamp": str(expiry_futures_market_info.expiration_timestamp), + "twapStartTimestamp": str(expiry_futures_market_info.twap_start_timestamp), + "expirationTwapStartPriceCumulative": expiry_futures_market_info.expiration_twap_start_price_cumulative, + "settlementPrice": expiry_futures_market_info.settlement_price, + } + } + + assert market_info == expected_market_info + + @pytest.mark.asyncio + async def test_fetch_perpetual_market_funding( + self, + exchange_servicer, + ): + perpetual_market_funding = exchange_pb.PerpetualMarketFunding( + cumulative_funding="-107853477278881692857461", + cumulative_price="0", + last_timestamp=1708099200, + ) + exchange_servicer.perpetual_market_funding_responses.append( + exchange_query_pb.QueryPerpetualMarketFundingResponse(state=perpetual_market_funding) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + funding = await api.fetch_perpetual_market_funding( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + ) + expected_funding = { + "state": { + "cumulativeFunding": perpetual_market_funding.cumulative_funding, + "cumulativePrice": perpetual_market_funding.cumulative_price, + "lastTimestamp": str(perpetual_market_funding.last_timestamp), + } + } + + assert funding == expected_funding + + @pytest.mark.asyncio + async def test_fetch_subaccount_order_metadata( + self, + exchange_servicer, + ): + metadata = exchange_pb.SubaccountOrderbookMetadata( + vanilla_limit_order_count=1, + reduce_only_limit_order_count=2, + aggregate_reduce_only_quantity="1000000000000000", + aggregate_vanilla_quantity="2000000000000000", + vanilla_conditional_order_count=3, + reduce_only_conditional_order_count=4, + ) + subaccount_order_metadata = exchange_query_pb.SubaccountOrderbookMetadataWithMarket( + metadata=metadata, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + isBuy=True, + ) + exchange_servicer.subaccount_order_metadata_responses.append( + exchange_query_pb.QuerySubaccountOrderMetadataResponse(metadata=[subaccount_order_metadata]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + metadata_response = await api.fetch_subaccount_order_metadata( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001" + ) + expected_metadata = { + "metadata": [ + { + "metadata": { + "vanillaLimitOrderCount": metadata.vanilla_limit_order_count, + "reduceOnlyLimitOrderCount": metadata.reduce_only_limit_order_count, + "aggregateReduceOnlyQuantity": metadata.aggregate_reduce_only_quantity, + "aggregateVanillaQuantity": metadata.aggregate_vanilla_quantity, + "vanillaConditionalOrderCount": metadata.vanilla_conditional_order_count, + "reduceOnlyConditionalOrderCount": metadata.reduce_only_conditional_order_count, + }, + "marketId": subaccount_order_metadata.market_id, + "isBuy": subaccount_order_metadata.isBuy, + }, + ] + } + + assert metadata_response == expected_metadata + + @pytest.mark.asyncio + async def test_fetch_trade_reward_points( + self, + exchange_servicer, + ): + points = "40" + response = exchange_query_pb.QueryTradeRewardPointsResponse(account_trade_reward_points=[points]) + exchange_servicer.trade_reward_points_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + trade_reward_points = await api.fetch_trade_reward_points( + accounts=["inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"], + pending_pool_timestamp=1708099200, + ) + expected_trade_reward_points = {"accountTradeRewardPoints": [points]} + + assert trade_reward_points == expected_trade_reward_points + + @pytest.mark.asyncio + async def test_fetch_pending_trade_reward_points( + self, + exchange_servicer, + ): + points = "40" + response = exchange_query_pb.QueryTradeRewardPointsResponse(account_trade_reward_points=[points]) + exchange_servicer.pending_trade_reward_points_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + trade_reward_points = await api.fetch_pending_trade_reward_points( + accounts=["inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"], + pending_pool_timestamp=1708099200, + ) + expected_trade_reward_points = {"accountTradeRewardPoints": [points]} + + assert trade_reward_points == expected_trade_reward_points + + @pytest.mark.asyncio + async def test_fetch_fee_discount_account_info( + self, + exchange_servicer, + ): + account_info = exchange_pb.FeeDiscountTierInfo( + maker_discount_rate="0.0001", + taker_discount_rate="0.0002", + staked_amount="1000000000", + volume="1000000000000000000", + ) + account_ttl = exchange_pb.FeeDiscountTierTTL( + tier=3, + ttl_timestamp=1708099200, + ) + response = exchange_query_pb.QueryFeeDiscountAccountInfoResponse( + tier_level=3, + account_info=account_info, + account_ttl=account_ttl, + ) + exchange_servicer.fee_discount_account_info_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + fee_discount = await api.fetch_fee_discount_account_info(account="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r") + expected_fee_discount = { + "tierLevel": str(response.tier_level), + "accountInfo": { + "makerDiscountRate": account_info.maker_discount_rate, + "takerDiscountRate": account_info.taker_discount_rate, + "stakedAmount": account_info.staked_amount, + "volume": account_info.volume, + }, + "accountTtl": { + "tier": str(account_ttl.tier), + "ttlTimestamp": str(account_ttl.ttl_timestamp), + }, + } + + assert fee_discount == expected_fee_discount + + @pytest.mark.asyncio + async def test_fetch_fee_discount_schedule( + self, + exchange_servicer, + ): + fee_discount_tier_info = exchange_pb.FeeDiscountTierInfo( + maker_discount_rate="0.0001", + taker_discount_rate="0.0002", + staked_amount="1000000000", + volume="1000000000000000000", + ) + fee_discount_schedule = exchange_pb.FeeDiscountSchedule( + bucket_count=3, + bucket_duration=3600, + quote_denoms=["peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"], + tier_infos=[fee_discount_tier_info], + disqualified_market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"], + ) + exchange_servicer.fee_discount_schedule_responses.append( + exchange_query_pb.QueryFeeDiscountScheduleResponse( + fee_discount_schedule=fee_discount_schedule, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + schedule = await api.fetch_fee_discount_schedule() + expected_schedule = { + "feeDiscountSchedule": { + "bucketCount": str(fee_discount_schedule.bucket_count), + "bucketDuration": str(fee_discount_schedule.bucket_duration), + "quoteDenoms": fee_discount_schedule.quote_denoms, + "tierInfos": [ + { + "makerDiscountRate": fee_discount_tier_info.maker_discount_rate, + "takerDiscountRate": fee_discount_tier_info.taker_discount_rate, + "stakedAmount": fee_discount_tier_info.staked_amount, + "volume": fee_discount_tier_info.volume, + } + ], + "disqualifiedMarketIds": fee_discount_schedule.disqualified_market_ids, + }, + } + + assert schedule == expected_schedule + + @pytest.mark.asyncio + async def test_fetch_balance_mismatches( + self, + exchange_servicer, + ): + balance_mismatch = exchange_query_pb.BalanceMismatch( + subaccountId="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + available="1000000000000000", + total="2000000000000000", + balance_hold="3000000000000000", + expected_total="4000000000000000", + difference="500000000000000", + ) + exchange_servicer.balance_mismatches_responses.append( + exchange_query_pb.QueryBalanceMismatchesResponse( + balance_mismatches=[balance_mismatch], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + mismatches = await api.fetch_balance_mismatches(dust_factor=20) + expected_mismatches = { + "balanceMismatches": [ + { + "subaccountId": balance_mismatch.subaccountId, + "denom": balance_mismatch.denom, + "available": balance_mismatch.available, + "total": balance_mismatch.total, + "balanceHold": balance_mismatch.balance_hold, + "expectedTotal": balance_mismatch.expected_total, + "difference": balance_mismatch.difference, + } + ], + } + + assert mismatches == expected_mismatches + + @pytest.mark.asyncio + async def test_fetch_balance_with_balance_holds( + self, + exchange_servicer, + ): + balance_with_balance_hold = exchange_query_pb.BalanceWithMarginHold( + subaccountId="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + available="1000000000000000", + total="2000000000000000", + balance_hold="3000000000000000", + ) + exchange_servicer.balance_with_balance_holds_responses.append( + exchange_query_pb.QueryBalanceWithBalanceHoldsResponse( + balance_with_balance_holds=[balance_with_balance_hold], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + balance = await api.fetch_balance_with_balance_holds() + expected_balance = { + "balanceWithBalanceHolds": [ + { + "subaccountId": balance_with_balance_hold.subaccountId, + "denom": balance_with_balance_hold.denom, + "available": balance_with_balance_hold.available, + "total": balance_with_balance_hold.total, + "balanceHold": balance_with_balance_hold.balance_hold, + } + ], + } + + assert balance == expected_balance + + @pytest.mark.asyncio + async def test_fetch_fee_discount_tier_statistics( + self, + exchange_servicer, + ): + tier_statistics = exchange_query_pb.TierStatistic( + tier=3, + count=30, + ) + exchange_servicer.fee_discount_tier_statistics_responses.append( + exchange_query_pb.QueryFeeDiscountTierStatisticsResponse( + statistics=[tier_statistics], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + statistics = await api.fetch_fee_discount_tier_statistics() + expected_statistics = { + "statistics": [ + { + "tier": str(tier_statistics.tier), + "count": str(tier_statistics.count), + } + ], + } + + assert statistics == expected_statistics + + @pytest.mark.asyncio + async def test_fetch_mito_vault_infos( + self, + exchange_servicer, + ): + master_address = "inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9" + derivative_address = "inj1zlh5" + spot_address = "inj1zlh6" + cw20_address = "inj1zlh7" + response = exchange_query_pb.MitoVaultInfosResponse( + master_addresses=[master_address], + derivative_addresses=[derivative_address], + spot_addresses=[spot_address], + cw20_addresses=[cw20_address], + ) + exchange_servicer.mito_vault_infos_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + mito_vaults = await api.fetch_mito_vault_infos() + expected_mito_vaults = { + "masterAddresses": [master_address], + "derivativeAddresses": [derivative_address], + "spotAddresses": [spot_address], + "cw20Addresses": [cw20_address], + } + + assert mito_vaults == expected_mito_vaults + + @pytest.mark.asyncio + async def test_fetch_market_id_from_vault( + self, + exchange_servicer, + ): + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + exchange_servicer.market_id_from_vault_responses.append( + exchange_query_pb.QueryMarketIDFromVaultResponse( + market_id=market_id, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + market_id_response = await api.fetch_market_id_from_vault( + vault_address="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9" + ) + expected_market_id = { + "marketId": market_id, + } + + assert market_id_response == expected_market_id + + @pytest.mark.asyncio + async def test_fetch_historical_trade_records( + self, + exchange_servicer, + ): + latest_trade_record = exchange_pb.TradeRecord( + timestamp=1708099200, + price="2000000000000000000", + quantity="1000000000000000", + ) + trade_record = exchange_pb.TradeRecords( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + latest_trade_records=[latest_trade_record], + ) + exchange_servicer.historical_trade_records_responses.append( + exchange_query_pb.QueryHistoricalTradeRecordsResponse( + trade_records=[trade_record], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + records = await api.fetch_historical_trade_records(market_id=trade_record.market_id) + expected_records = { + "tradeRecords": [ + { + "marketId": trade_record.market_id, + "latestTradeRecords": [ + { + "timestamp": str(latest_trade_record.timestamp), + "price": latest_trade_record.price, + "quantity": latest_trade_record.quantity, + } + ], + }, + ], + } + + assert records == expected_records + + @pytest.mark.asyncio + async def test_fetch_is_opted_out_of_rewards( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryIsOptedOutOfRewardsResponse( + is_opted_out=False, + ) + exchange_servicer.is_opted_out_of_rewards_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + is_opted_out = await api.fetch_is_opted_out_of_rewards(account="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9") + expected_is_opted_out = { + "isOptedOut": response.is_opted_out, + } + + assert is_opted_out == expected_is_opted_out + + @pytest.mark.asyncio + async def test_fetch_opted_out_of_rewards_accounts( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryOptedOutOfRewardsAccountsResponse( + accounts=["inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9"], + ) + exchange_servicer.opted_out_of_rewards_accounts_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + opted_out = await api.fetch_opted_out_of_rewards_accounts() + expected_opted_out = { + "accounts": response.accounts, + } + + assert opted_out == expected_opted_out + + @pytest.mark.asyncio + async def test_fetch_market_volatility( + self, + exchange_servicer, + ): + history_metadata = oracle_pb.MetadataStatistics( + group_count=2, + records_sample_size=10, + mean="0.0001", + twap="0.0005", + first_timestamp=1702399200, + last_timestamp=1708099200, + min_price="1000000000000", + max_price="3000000000000", + median_price="2000000000000", + ) + trade_record = exchange_pb.TradeRecord( + timestamp=1708099200, + price="2000000000000000000", + quantity="1000000000000000", + ) + response = exchange_query_pb.QueryMarketVolatilityResponse( + volatility="0.0001", history_metadata=history_metadata, raw_history=[trade_record] + ) + exchange_servicer.market_volatility_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volatility = await api.fetch_market_volatility( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + trade_grouping_sec=0, + max_age=28000000, + include_raw_history=True, + include_metadata=True, + ) + expected_volatility = { + "volatility": response.volatility, + "historyMetadata": { + "groupCount": history_metadata.group_count, + "recordsSampleSize": history_metadata.records_sample_size, + "mean": history_metadata.mean, + "twap": history_metadata.twap, + "firstTimestamp": str(history_metadata.first_timestamp), + "lastTimestamp": str(history_metadata.last_timestamp), + "minPrice": history_metadata.min_price, + "maxPrice": history_metadata.max_price, + "medianPrice": history_metadata.median_price, + }, + "rawHistory": [ + { + "timestamp": str(trade_record.timestamp), + "price": trade_record.price, + "quantity": trade_record.quantity, + } + ], + } + + assert volatility == expected_volatility + + @pytest.mark.asyncio + async def test_fetch_binary_options_markets( + self, + exchange_servicer, + ): + market = exchange_pb.BinaryOptionsMarket( + ticker="20250608/USDT", + oracle_symbol="0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3", + oracle_provider="Pyth", + oracle_type=9, + oracle_scale_factor=6, + expiration_timestamp=1708099200, + settlement_timestamp=1707099200, + admin="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="400000000000000000", + status=1, + min_price_tick_size="100000000000000000000", + min_quantity_tick_size="1000000000000000", + settlement_price="2000000000000000000", + ) + response = exchange_query_pb.QueryBinaryMarketsResponse( + markets=[market], + ) + exchange_servicer.binary_options_markets_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + markets = await api.fetch_binary_options_markets(status="Active") + expected_markets = { + "markets": [ + { + "ticker": market.ticker, + "oracleSymbol": market.oracle_symbol, + "oracleProvider": market.oracle_provider, + "oracleType": oracle_pb.OracleType.Name(market.oracle_type), + "oracleScaleFactor": market.oracle_scale_factor, + "expirationTimestamp": str(market.expiration_timestamp), + "settlementTimestamp": str(market.settlement_timestamp), + "admin": market.admin, + "quoteDenom": market.quote_denom, + "marketId": market.market_id, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "status": exchange_pb.MarketStatus.Name(market.status), + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + "settlementPrice": market.settlement_price, + }, + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_trader_derivative_conditional_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeConditionalOrder( + price="2000000000000000000", + quantity="1000000000000000", + margin="2000000000000000000000000000000000", + triggerPrice="3000000000000000000", + isBuy=True, + isLimit=True, + order_hash="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + response = exchange_query_pb.QueryTraderDerivativeConditionalOrdersResponse(orders=[order]) + exchange_servicer.trader_derivative_conditional_orders_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_derivative_conditional_orders( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "triggerPrice": order.triggerPrice, + "isBuy": order.isBuy, + "isLimit": order.isLimit, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_market_atomic_execution_fee_multiplier( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryMarketAtomicExecutionFeeMultiplierResponse( + multiplier="100", + ) + exchange_servicer.market_atomic_execution_fee_multiplier_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + multiplier = await api.fetch_market_atomic_execution_fee_multiplier( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + expected_multiplier = { + "multiplier": response.multiplier, + } + + assert multiplier == expected_multiplier + + async def _dummy_metadata_provider(self): + return None From c5cb600d9eae68f16d7180d0065230d5c98793e8 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 27 Feb 2024 10:03:11 -0300 Subject: [PATCH 22/44] (feat) Added support for all chain exchange module messages in Composer. Added unit tests for new messages. Refactored example scripts to move them into separated subfolders for each module. --- ..._LocalOrderHash.py => 1_LocalOrderHash.py} | 101 +- ...OrderFail.py => 2_StreamEventOrderFail.py} | 0 .../35_MsgInstantBinaryOptionsMarketLaunch.py | 98 - ...Broadcaster.py => 3_MessageBroadcaster.py} | 21 +- ...4_MessageBroadcasterWithGranteeAccount.py} | 12 +- ... 5_MessageBroadcasterWithoutSimulation.py} | 19 +- ...terWithGranteeAccountWithoutSimulation.py} | 12 +- .../{49_ChainStream.py => 7_ChainStream.py} | 0 .../{18_MsgBid.py => auction/1_MsgBid.py} | 0 .../query/1_Account.py} | 0 .../{19_MsgGrant.py => authz/1_MsgGrant.py} | 0 .../{20_MsgExec.py => authz/2_MsgExec.py} | 10 +- .../{21_MsgRevoke.py => authz/3_MsgRevoke.py} | 0 .../4_MsgExecuteContractCompat.py} | 0 .../{27_Grants.py => authz/query/1_Grants.py} | 0 examples/chain_client/{ => bank}/1_MsgSend.py | 0 .../query/10_SendEnabled.py} | 0 .../query/1_BankBalance.py} | 0 .../query/2_BankBalances.py} | 0 .../query/3_SpendableBalances.py} | 0 .../query/4_SpendableBalancesByDenom.py} | 0 .../query/5_TotalSupply.py} | 0 .../query/6_SupplyOf.py} | 0 .../query/7_DenomMetadata.py} | 0 .../query/8_DenomsMetadata.py} | 0 .../query/9_DenomOwners.py} | 0 ...py => 10_MsgCreateDerivativeLimitOrder.py} | 14 +- ...y => 11_MsgCreateDerivativeMarketOrder.py} | 12 +- ...rder.py => 12_MsgCancelDerivativeOrder.py} | 2 +- .../13_MsgInstantBinaryOptionsMarketLaunch.py | 61 + ...=> 14_MsgCreateBinaryOptionsLimitOrder.py} | 13 +- ...> 15_MsgCreateBinaryOptionsMarketOrder.py} | 12 +- ...r.py => 16_MsgCancelBinaryOptionsOrder.py} | 2 +- ...ransfer.py => 17_MsgSubaccountTransfer.py} | 5 +- ...lTransfer.py => 18_MsgExternalTransfer.py} | 5 +- .../exchange/19_MsgLiquidatePosition.py | 15 +- .../chain_client/exchange/1_MsgDeposit.py | 4 +- .../20_MsgIncreasePositionMargin.py} | 5 +- ...ewardsOptOut.py => 21_MsgRewardsOptOut.py} | 2 +- .../22_MsgAdminUpdateBinaryOptionsMarket.py} | 5 +- .../{9_MsgWithdraw.py => 2_MsgWithdraw.py} | 2 +- .../exchange/3_MsgInstantSpotMarketLaunch.py | 54 + .../4_MsgInstantPerpetualMarketLaunch.py | 61 + .../5_MsgInstantExpiryFuturesMarketLaunch.py | 62 + ...tOrder.py => 6_MsgCreateSpotLimitOrder.py} | 10 +- ...Order.py => 7_MsgCreateSpotMarketOrder.py} | 11 +- ...elSpotOrder.py => 8_MsgCancelSpotOrder.py} | 0 ...ateOrders.py => 9_MsgBatchUpdateOrders.py} | 53 +- .../1_MsgCreateInsuranceFund.py} | 0 .../2_MsgUnderwrite.py} | 0 .../3_MsgRequestRedemption.py} | 0 .../1_MsgRelayPriceFeedPrice.py} | 0 .../2_MsgRelayProviderPrices.py} | 0 .../1_MsgSendToEth.py} | 0 .../1_MsgDelegate.py} | 0 .../1_CreateDenom.py} | 0 .../2_MsgMint.py} | 0 .../3_MsgBurn.py} | 0 .../4_MsgChangeAdmin.py} | 0 .../5_MsgSetDenomMetadata.py} | 0 .../query/1_DenomAuthorityMetadata.py} | 0 .../query/2_DenomsFromCreator.py} | 0 .../query/3_TokenfactoryModuleState.py} | 0 .../{37_GetTx.py => tx/query/1_GetTx.py} | 0 .../1_MsgExecuteContract.py} | 0 .../query/10_ContractsByCreator.py} | 0 .../query/1_ContractInfo.py} | 0 .../query/2_ContractHistory.py} | 0 .../query/3_ContractsByCode.py} | 0 .../query/4_AllContractsState.py} | 0 .../query/5_RawContractState.py} | 0 .../query/6_SmartContractState.py} | 0 .../query/7_SmartContractCode.py} | 0 .../query/8_SmartContractCodes.py} | 0 .../query/9_SmartContractPinnedCodes.py} | 0 pyinjective/composer.py | 1751 +++++++++++++---- pyinjective/core/market.py | 11 + tests/core/test_gas_limit_estimator.py | 158 +- tests/core/test_market.py | 36 + ...essage_based_transaction_fee_calculator.py | 27 +- tests/test_composer.py | 1466 ++++++++++++-- tests/test_composer_deprecation_warnings.py | 522 +++++ tests/test_orderhash.py | 20 +- 83 files changed, 3740 insertions(+), 934 deletions(-) rename examples/chain_client/{0_LocalOrderHash.py => 1_LocalOrderHash.py} (75%) rename examples/chain_client/{38_StreamEventOrderFail.py => 2_StreamEventOrderFail.py} (100%) delete mode 100644 examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py rename examples/chain_client/{44_MessageBroadcaster.py => 3_MessageBroadcaster.py} (84%) rename examples/chain_client/{45_MessageBroadcasterWithGranteeAccount.py => 4_MessageBroadcasterWithGranteeAccount.py} (91%) rename examples/chain_client/{46_MessageBroadcasterWithoutSimulation.py => 5_MessageBroadcasterWithoutSimulation.py} (86%) rename examples/chain_client/{47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py => 6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py} (91%) rename examples/chain_client/{49_ChainStream.py => 7_ChainStream.py} (100%) rename examples/chain_client/{18_MsgBid.py => auction/1_MsgBid.py} (100%) rename examples/chain_client/{39_Account.py => auth/query/1_Account.py} (100%) rename examples/chain_client/{19_MsgGrant.py => authz/1_MsgGrant.py} (100%) rename examples/chain_client/{20_MsgExec.py => authz/2_MsgExec.py} (95%) rename examples/chain_client/{21_MsgRevoke.py => authz/3_MsgRevoke.py} (100%) rename examples/chain_client/{76_MsgExecuteContractCompat.py => authz/4_MsgExecuteContractCompat.py} (100%) rename examples/chain_client/{27_Grants.py => authz/query/1_Grants.py} (100%) rename examples/chain_client/{ => bank}/1_MsgSend.py (100%) rename examples/chain_client/{57_SendEnabled.py => bank/query/10_SendEnabled.py} (100%) rename examples/chain_client/{29_BankBalance.py => bank/query/1_BankBalance.py} (100%) rename examples/chain_client/{28_BankBalances.py => bank/query/2_BankBalances.py} (100%) rename examples/chain_client/{50_SpendableBalances.py => bank/query/3_SpendableBalances.py} (100%) rename examples/chain_client/{51_SpendableBalancesByDenom.py => bank/query/4_SpendableBalancesByDenom.py} (100%) rename examples/chain_client/{52_TotalSupply.py => bank/query/5_TotalSupply.py} (100%) rename examples/chain_client/{53_SupplyOf.py => bank/query/6_SupplyOf.py} (100%) rename examples/chain_client/{54_DenomMetadata.py => bank/query/7_DenomMetadata.py} (100%) rename examples/chain_client/{55_DenomsMetadata.py => bank/query/8_DenomsMetadata.py} (100%) rename examples/chain_client/{56_DenomOwners.py => bank/query/9_DenomOwners.py} (100%) rename examples/chain_client/exchange/{6_MsgCreateDerivativeLimitOrder.py => 10_MsgCreateDerivativeLimitOrder.py} (90%) rename examples/chain_client/exchange/{7_MsgCreateDerivativeMarketOrder.py => 11_MsgCreateDerivativeMarketOrder.py} (90%) rename examples/chain_client/exchange/{8_MsgCancelDerivativeOrder.py => 12_MsgCancelDerivativeOrder.py} (98%) create mode 100644 examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py rename examples/chain_client/exchange/{16_MsgCreateBinaryOptionsLimitOrder.py => 14_MsgCreateBinaryOptionsLimitOrder.py} (93%) rename examples/chain_client/exchange/{17_MsgCreateBinaryOptionsMarketOrder.py => 15_MsgCreateBinaryOptionsMarketOrder.py} (90%) rename examples/chain_client/exchange/{18_MsgCancelBinaryOptionsOrder.py => 16_MsgCancelBinaryOptionsOrder.py} (98%) rename examples/chain_client/exchange/{10_MsgSubaccountTransfer.py => 17_MsgSubaccountTransfer.py} (96%) rename examples/chain_client/exchange/{15_ExternalTransfer.py => 18_MsgExternalTransfer.py} (96%) rename examples/chain_client/{13_MsgIncreasePositionMargin.py => exchange/20_MsgIncreasePositionMargin.py} (96%) rename examples/chain_client/exchange/{12_MsgRewardsOptOut.py => 21_MsgRewardsOptOut.py} (97%) rename examples/chain_client/{34_MsgAdminUpdateBinaryOptionsMarket.py => exchange/22_MsgAdminUpdateBinaryOptionsMarket.py} (96%) rename examples/chain_client/exchange/{9_MsgWithdraw.py => 2_MsgWithdraw.py} (95%) create mode 100644 examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py create mode 100644 examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py create mode 100644 examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py rename examples/chain_client/exchange/{3_MsgCreateSpotLimitOrder.py => 6_MsgCreateSpotLimitOrder.py} (94%) rename examples/chain_client/exchange/{4_MsgCreateSpotMarketOrder.py => 7_MsgCreateSpotMarketOrder.py} (94%) rename examples/chain_client/exchange/{5_MsgCancelSpotOrder.py => 8_MsgCancelSpotOrder.py} (100%) rename examples/chain_client/exchange/{11_MsgBatchUpdateOrders.py => 9_MsgBatchUpdateOrders.py} (83%) rename examples/chain_client/{41_MsgCreateInsuranceFund.py => insurance/1_MsgCreateInsuranceFund.py} (100%) rename examples/chain_client/{42_MsgUnderwrite.py => insurance/2_MsgUnderwrite.py} (100%) rename examples/chain_client/{43_MsgRequestRedemption.py => insurance/3_MsgRequestRedemption.py} (100%) rename examples/chain_client/{23_MsgRelayPriceFeedPrice.py => oracle/1_MsgRelayPriceFeedPrice.py} (100%) rename examples/chain_client/{36_MsgRelayProviderPrices.py => oracle/2_MsgRelayProviderPrices.py} (100%) rename examples/chain_client/{22_MsgSendToEth.py => peggy/1_MsgSendToEth.py} (100%) rename examples/chain_client/{25_MsgDelegate.py => staking/1_MsgDelegate.py} (100%) rename examples/chain_client/{71_CreateDenom.py => tokenfactory/1_CreateDenom.py} (100%) rename examples/chain_client/{72_MsgMint.py => tokenfactory/2_MsgMint.py} (100%) rename examples/chain_client/{73_MsgBurn.py => tokenfactory/3_MsgBurn.py} (100%) rename examples/chain_client/{75_MsgChangeAdmin.py => tokenfactory/4_MsgChangeAdmin.py} (100%) rename examples/chain_client/{74_MsgSetDenomMetadata.py => tokenfactory/5_MsgSetDenomMetadata.py} (100%) rename examples/chain_client/{68_DenomAuthorityMetadata.py => tokenfactory/query/1_DenomAuthorityMetadata.py} (100%) rename examples/chain_client/{69_DenomsFromCreator.py => tokenfactory/query/2_DenomsFromCreator.py} (100%) rename examples/chain_client/{70_TokenfactoryModuleState.py => tokenfactory/query/3_TokenfactoryModuleState.py} (100%) rename examples/chain_client/{37_GetTx.py => tx/query/1_GetTx.py} (100%) rename examples/chain_client/{40_MsgExecuteContract.py => wasm/1_MsgExecuteContract.py} (100%) rename examples/chain_client/{67_ContractsByCreator.py => wasm/query/10_ContractsByCreator.py} (100%) rename examples/chain_client/{58_ContractInfo.py => wasm/query/1_ContractInfo.py} (100%) rename examples/chain_client/{59_ContractHistory.py => wasm/query/2_ContractHistory.py} (100%) rename examples/chain_client/{60_ContractsByCode.py => wasm/query/3_ContractsByCode.py} (100%) rename examples/chain_client/{61_AllContractsState.py => wasm/query/4_AllContractsState.py} (100%) rename examples/chain_client/{62_RawContractState.py => wasm/query/5_RawContractState.py} (100%) rename examples/chain_client/{63_SmartContractState.py => wasm/query/6_SmartContractState.py} (100%) rename examples/chain_client/{64_SmartContractCode.py => wasm/query/7_SmartContractCode.py} (100%) rename examples/chain_client/{65_SmartContractCodes.py => wasm/query/8_SmartContractCodes.py} (100%) rename examples/chain_client/{66_SmartContractPinnedCodes.py => wasm/query/9_SmartContractPinnedCodes.py} (100%) create mode 100644 tests/test_composer_deprecation_warnings.py diff --git a/examples/chain_client/0_LocalOrderHash.py b/examples/chain_client/1_LocalOrderHash.py similarity index 75% rename from examples/chain_client/0_LocalOrderHash.py rename to examples/chain_client/1_LocalOrderHash.py index 770ad5bf..fbec8988 100644 --- a/examples/chain_client/0_LocalOrderHash.py +++ b/examples/chain_client/1_LocalOrderHash.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -40,57 +41,59 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" spot_orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.524, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("0.524"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=27.92, - quantity=0.01, - is_buy=False, - is_po=False, + price=Decimal("27.92"), + quantity=Decimal("0.01"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] derivative_orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=10500, - quantity=0.01, - leverage=1.5, - is_buy=True, - is_po=False, + price=Decimal(10500), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(10500), leverage=Decimal(2), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=65111, - quantity=0.01, - leverage=2, - is_buy=False, - is_reduce_only=False, + price=Decimal(65111), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(65111), leverage=Decimal(2), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ), ] # prepare tx msg - spot_msg = composer.MsgBatchCreateSpotLimitOrders(sender=address.to_acc_bech32(), orders=spot_orders) + spot_msg = composer.msg_batch_create_spot_limit_orders(sender=address.to_acc_bech32(), orders=spot_orders) - deriv_msg = composer.MsgBatchCreateDerivativeLimitOrders(sender=address.to_acc_bech32(), orders=derivative_orders) + deriv_msg = composer.msg_batch_create_derivative_limit_orders( + sender=address.to_acc_bech32(), orders=derivative_orders + ) # compute order hashes order_hashes = order_hash_manager.compute_order_hashes( @@ -167,57 +170,59 @@ async def main() -> None: print("gas fee: {} INJ".format(gas_fee)) spot_orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=1.524, - quantity=0.01, - is_buy=True, - is_po=True, + price=Decimal("1.524"), + quantity=Decimal("0.01"), + order_type="BUY_PO", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=27.92, - quantity=0.01, - is_buy=False, - is_po=False, + price=Decimal("27.92"), + quantity=Decimal("0.01"), + order_type="SELL_PO", cid=str(uuid.uuid4()), ), ] derivative_orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=25111, - quantity=0.01, - leverage=1.5, - is_buy=True, - is_po=False, + price=Decimal(25111), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(25111), leverage=Decimal("1.5"), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=65111, - quantity=0.01, - leverage=2, - is_buy=False, - is_reduce_only=False, + price=Decimal(65111), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(25111), leverage=Decimal(2), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ), ] # prepare tx msg - spot_msg = composer.MsgBatchCreateSpotLimitOrders(sender=address.to_acc_bech32(), orders=spot_orders) + spot_msg = composer.msg_batch_create_spot_limit_orders(sender=address.to_acc_bech32(), orders=spot_orders) - deriv_msg = composer.MsgBatchCreateDerivativeLimitOrders(sender=address.to_acc_bech32(), orders=derivative_orders) + deriv_msg = composer.msg_batch_create_derivative_limit_orders( + sender=address.to_acc_bech32(), orders=derivative_orders + ) # compute order hashes order_hashes = order_hash_manager.compute_order_hashes( diff --git a/examples/chain_client/38_StreamEventOrderFail.py b/examples/chain_client/2_StreamEventOrderFail.py similarity index 100% rename from examples/chain_client/38_StreamEventOrderFail.py rename to examples/chain_client/2_StreamEventOrderFail.py diff --git a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py deleted file mode 100644 index 7b8a6567..00000000 --- a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py +++ /dev/null @@ -1,98 +0,0 @@ -import asyncio -import os - -import dotenv -from grpc import RpcError - -from pyinjective.async_client import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE -from pyinjective.core.network import Network -from pyinjective.transaction import Transaction -from pyinjective.wallet import PrivateKey - - -async def main() -> None: - dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") - - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - composer = await client.composer() - await client.sync_timeout_height() - - # load account - priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - # prepare tx msg - msg = composer.MsgInstantBinaryOptionsMarketLaunch( - sender=address.to_acc_bech32(), - admin=address.to_acc_bech32(), - ticker="UFC-KHABIB-TKO-05/30/2023", - oracle_symbol="UFC-KHABIB-TKO-05/30/2023", - oracle_provider="UFC", - oracle_type="Provider", - quote_denom="peggy0xdAC17F958D2ee523a2206206994597C13D831ec7", - quote_decimals=6, - oracle_scale_factor=6, - maker_fee_rate=0.0005, # 0.05% - taker_fee_rate=0.0010, # 0.10% - expiration_timestamp=1680730982, - settlement_timestamp=1690730982, - min_price_tick_size=0.01, - min_quantity_tick_size=0.01, - ) - - # build sim tx - tx = ( - Transaction() - .with_messages(msg) - .with_sequence(client.get_sequence()) - .with_account_num(client.get_number()) - .with_chain_id(network.chain_id) - ) - sim_sign_doc = tx.get_sign_doc(pub_key) - sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) - sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key) - - # simulate tx - try: - sim_res = await client.simulate(sim_tx_raw_bytes) - except RpcError as ex: - print(ex) - return - - sim_res_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) - - # build tx - gas_price = GAS_PRICE - gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation - gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") - fee = [ - composer.coin( - amount=gas_price * gas_limit, - denom=network.fee_denom, - ) - ] - tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height) - sign_doc = tx.get_sign_doc(pub_key) - sig = priv_key.sign(sign_doc.SerializeToString()) - tx_raw_bytes = tx.get_tx_data(sig, pub_key) - - # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode - res = await client.broadcast_tx_sync_mode(tx_raw_bytes) - print("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/44_MessageBroadcaster.py b/examples/chain_client/3_MessageBroadcaster.py similarity index 84% rename from examples/chain_client/44_MessageBroadcaster.py rename to examples/chain_client/3_MessageBroadcaster.py index 114a8700..6bd67033 100644 --- a/examples/chain_client/44_MessageBroadcaster.py +++ b/examples/chain_client/3_MessageBroadcaster.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -34,24 +35,22 @@ async def main() -> None: spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" spot_orders_to_create = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=3, - quantity=55, - is_buy=True, - is_po=False, - cid=str(uuid.uuid4()), + price=Decimal("3"), + quantity=Decimal("55"), + order_type="BUY", + cid=(str(uuid.uuid4())), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=300, - quantity=55, - is_buy=False, - is_po=False, + price=Decimal("300"), + quantity=Decimal("55"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] diff --git a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py b/examples/chain_client/4_MessageBroadcasterWithGranteeAccount.py similarity index 91% rename from examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py rename to examples/chain_client/4_MessageBroadcasterWithGranteeAccount.py index 8c0166e2..4e08397b 100644 --- a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py +++ b/examples/chain_client/4_MessageBroadcasterWithGranteeAccount.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -40,15 +41,14 @@ async def main() -> None: granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) - msg = composer.MsgCreateSpotLimitOrder( - sender=granter_inj_address, + msg = composer.msg_create_spot_limit_order( market_id=market_id, + sender=granter_inj_address, subaccount_id=granter_subaccount_id, fee_recipient=address.to_acc_bech32(), - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py b/examples/chain_client/5_MessageBroadcasterWithoutSimulation.py similarity index 86% rename from examples/chain_client/46_MessageBroadcasterWithoutSimulation.py rename to examples/chain_client/5_MessageBroadcasterWithoutSimulation.py index e6e87c5a..54a79bf8 100644 --- a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py +++ b/examples/chain_client/5_MessageBroadcasterWithoutSimulation.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -34,24 +35,22 @@ async def main() -> None: spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" spot_orders_to_create = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=3, - quantity=55, - is_buy=True, - is_po=False, + price=Decimal("3"), + quantity=Decimal("55"), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=300, - quantity=55, - is_buy=False, - is_po=False, + price=Decimal("300"), + quantity=Decimal("55"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] diff --git a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py b/examples/chain_client/6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py similarity index 91% rename from examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py rename to examples/chain_client/6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py index b95114b7..4b7fbd2e 100644 --- a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py +++ b/examples/chain_client/6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -39,15 +40,14 @@ async def main() -> None: granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) - msg = composer.MsgCreateSpotLimitOrder( - sender=granter_inj_address, + msg = composer.msg_create_spot_limit_order( market_id=market_id, + sender=granter_inj_address, subaccount_id=granter_subaccount_id, fee_recipient=address.to_acc_bech32(), - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/49_ChainStream.py b/examples/chain_client/7_ChainStream.py similarity index 100% rename from examples/chain_client/49_ChainStream.py rename to examples/chain_client/7_ChainStream.py diff --git a/examples/chain_client/18_MsgBid.py b/examples/chain_client/auction/1_MsgBid.py similarity index 100% rename from examples/chain_client/18_MsgBid.py rename to examples/chain_client/auction/1_MsgBid.py diff --git a/examples/chain_client/39_Account.py b/examples/chain_client/auth/query/1_Account.py similarity index 100% rename from examples/chain_client/39_Account.py rename to examples/chain_client/auth/query/1_Account.py diff --git a/examples/chain_client/19_MsgGrant.py b/examples/chain_client/authz/1_MsgGrant.py similarity index 100% rename from examples/chain_client/19_MsgGrant.py rename to examples/chain_client/authz/1_MsgGrant.py diff --git a/examples/chain_client/20_MsgExec.py b/examples/chain_client/authz/2_MsgExec.py similarity index 95% rename from examples/chain_client/20_MsgExec.py rename to examples/chain_client/authz/2_MsgExec.py index 1203ff90..8d9891a5 100644 --- a/examples/chain_client/20_MsgExec.py +++ b/examples/chain_client/authz/2_MsgExec.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -37,15 +38,14 @@ async def main() -> None: granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) - msg0 = composer.MsgCreateSpotLimitOrder( + msg0 = composer.msg_create_spot_limit_order( sender=granter_inj_address, market_id=market_id, subaccount_id=granter_subaccount_id, fee_recipient=grantee, - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/21_MsgRevoke.py b/examples/chain_client/authz/3_MsgRevoke.py similarity index 100% rename from examples/chain_client/21_MsgRevoke.py rename to examples/chain_client/authz/3_MsgRevoke.py diff --git a/examples/chain_client/76_MsgExecuteContractCompat.py b/examples/chain_client/authz/4_MsgExecuteContractCompat.py similarity index 100% rename from examples/chain_client/76_MsgExecuteContractCompat.py rename to examples/chain_client/authz/4_MsgExecuteContractCompat.py diff --git a/examples/chain_client/27_Grants.py b/examples/chain_client/authz/query/1_Grants.py similarity index 100% rename from examples/chain_client/27_Grants.py rename to examples/chain_client/authz/query/1_Grants.py diff --git a/examples/chain_client/1_MsgSend.py b/examples/chain_client/bank/1_MsgSend.py similarity index 100% rename from examples/chain_client/1_MsgSend.py rename to examples/chain_client/bank/1_MsgSend.py diff --git a/examples/chain_client/57_SendEnabled.py b/examples/chain_client/bank/query/10_SendEnabled.py similarity index 100% rename from examples/chain_client/57_SendEnabled.py rename to examples/chain_client/bank/query/10_SendEnabled.py diff --git a/examples/chain_client/29_BankBalance.py b/examples/chain_client/bank/query/1_BankBalance.py similarity index 100% rename from examples/chain_client/29_BankBalance.py rename to examples/chain_client/bank/query/1_BankBalance.py diff --git a/examples/chain_client/28_BankBalances.py b/examples/chain_client/bank/query/2_BankBalances.py similarity index 100% rename from examples/chain_client/28_BankBalances.py rename to examples/chain_client/bank/query/2_BankBalances.py diff --git a/examples/chain_client/50_SpendableBalances.py b/examples/chain_client/bank/query/3_SpendableBalances.py similarity index 100% rename from examples/chain_client/50_SpendableBalances.py rename to examples/chain_client/bank/query/3_SpendableBalances.py diff --git a/examples/chain_client/51_SpendableBalancesByDenom.py b/examples/chain_client/bank/query/4_SpendableBalancesByDenom.py similarity index 100% rename from examples/chain_client/51_SpendableBalancesByDenom.py rename to examples/chain_client/bank/query/4_SpendableBalancesByDenom.py diff --git a/examples/chain_client/52_TotalSupply.py b/examples/chain_client/bank/query/5_TotalSupply.py similarity index 100% rename from examples/chain_client/52_TotalSupply.py rename to examples/chain_client/bank/query/5_TotalSupply.py diff --git a/examples/chain_client/53_SupplyOf.py b/examples/chain_client/bank/query/6_SupplyOf.py similarity index 100% rename from examples/chain_client/53_SupplyOf.py rename to examples/chain_client/bank/query/6_SupplyOf.py diff --git a/examples/chain_client/54_DenomMetadata.py b/examples/chain_client/bank/query/7_DenomMetadata.py similarity index 100% rename from examples/chain_client/54_DenomMetadata.py rename to examples/chain_client/bank/query/7_DenomMetadata.py diff --git a/examples/chain_client/55_DenomsMetadata.py b/examples/chain_client/bank/query/8_DenomsMetadata.py similarity index 100% rename from examples/chain_client/55_DenomsMetadata.py rename to examples/chain_client/bank/query/8_DenomsMetadata.py diff --git a/examples/chain_client/56_DenomOwners.py b/examples/chain_client/bank/query/9_DenomOwners.py similarity index 100% rename from examples/chain_client/56_DenomOwners.py rename to examples/chain_client/bank/query/9_DenomOwners.py diff --git a/examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py similarity index 90% rename from examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py rename to examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py index 41a19307..4e0ff327 100644 --- a/examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,16 +37,17 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateDerivativeLimitOrder( + msg = composer.msg_create_derivative_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=50000, - quantity=0.1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(50000), + quantity=Decimal(0.1), + margin=composer.calculate_margin( + quantity=Decimal(0.1), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py similarity index 90% rename from examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py rename to examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py index 37b305ed..dfedf6d6 100644 --- a/examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py +++ b/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,15 +37,16 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateDerivativeMarketOrder( + msg = composer.msg_create_derivative_market_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=50000, - quantity=0.01, - leverage=3, - is_buy=True, + price=Decimal(50000), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(50000), leverage=Decimal(3), is_reduce_only=False + ), cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py b/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py similarity index 98% rename from examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py rename to examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py index 43180b1f..20be2bd0 100644 --- a/examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py +++ b/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py @@ -35,7 +35,7 @@ async def main() -> None: order_hash = "0x667ee6f37f6d06bf473f4e1434e92ac98ff43c785405e2a511a0843daeca2de9" # prepare tx msg - msg = composer.MsgCancelDerivativeOrder( + msg = composer.msg_cancel_derivative_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash ) diff --git a/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py new file mode 100644 index 00000000..a1ebde82 --- /dev/null +++ b/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py @@ -0,0 +1,61 @@ +import asyncio +import os + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + composer = await client.composer() + await client.sync_timeout_height() + + message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( + network=network, + private_key=configured_private_key, + ) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + message = composer.msg_instant_binary_options_market_launch( + sender=address.to_acc_bech32(), + ticker="UFC-KHABIB-TKO-05/30/2023", + oracle_symbol="UFC-KHABIB-TKO-05/30/2023", + oracle_provider="UFC", + oracle_type="Provider", + quote_decimals=6, + oracle_scale_factor=6, + maker_fee_rate=0.0005, # 0.05% + taker_fee_rate=0.0010, # 0.10% + expiration_timestamp=1680730982, + settlement_timestamp=1690730982, + admin=address.to_acc_bech32(), + quote_denom="peggy0xdAC17F958D2ee523a2206206994597C13D831ec7", + min_price_tick_size=0.01, + min_quantity_tick_size=0.01, + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py similarity index 93% rename from examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py rename to examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py index 2a58e173..5ad8c59e 100644 --- a/examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py +++ b/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -40,17 +41,17 @@ async def main() -> None: denom = Denom(description="desc", base=0, quote=6, min_price_tick_size=1000, min_quantity_tick_size=0.0001) # prepare tx msg - msg = composer.MsgCreateBinaryOptionsLimitOrder( + msg = composer.msg_create_binary_options_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.5, - quantity=1, - is_buy=False, - is_reduce_only=False, - denom=denom, + price=Decimal("0.5"), + quantity=Decimal("1"), + margin=Decimal("0.5"), + order_type="BUY", cid=str(uuid.uuid4()), + denom=denom, ) # build sim tx diff --git a/examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py similarity index 90% rename from examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py rename to examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py index 2d07658f..9b68bc85 100644 --- a/examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py +++ b/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,15 +37,16 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateBinaryOptionsMarketOrder( + msg = composer.msg_create_binary_options_market_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.5, - quantity=1, - is_buy=True, - is_reduce_only=False, + price=Decimal("0.5"), + quantity=Decimal(1), + margin=composer.calculate_margin( + quantity=Decimal(1), price=Decimal("0.5"), leverage=Decimal(1), is_reduce_only=False + ), cid=str(uuid.uuid4()), ) # build sim tx diff --git a/examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py similarity index 98% rename from examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py rename to examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py index 82107f3c..582c6dc6 100644 --- a/examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py +++ b/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py @@ -35,7 +35,7 @@ async def main() -> None: order_hash = "a975fbd72b874bdbf5caf5e1e8e2653937f33ce6dd14d241c06c8b1f7b56be46" # prepare tx msg - msg = composer.MsgCancelBinaryOptionsOrder( + msg = composer.msg_cancel_binary_options_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash ) # build sim tx diff --git a/examples/chain_client/exchange/10_MsgSubaccountTransfer.py b/examples/chain_client/exchange/17_MsgSubaccountTransfer.py similarity index 96% rename from examples/chain_client/exchange/10_MsgSubaccountTransfer.py rename to examples/chain_client/exchange/17_MsgSubaccountTransfer.py index b68717b2..a50fc0cf 100644 --- a/examples/chain_client/exchange/10_MsgSubaccountTransfer.py +++ b/examples/chain_client/exchange/17_MsgSubaccountTransfer.py @@ -1,5 +1,6 @@ import asyncio import os +from decimal import Decimal import dotenv from grpc import RpcError @@ -32,11 +33,11 @@ async def main() -> None: dest_subaccount_id = address.get_subaccount_id(index=1) # prepare tx msg - msg = composer.MsgSubaccountTransfer( + msg = composer.msg_subaccount_transfer( sender=address.to_acc_bech32(), source_subaccount_id=subaccount_id, destination_subaccount_id=dest_subaccount_id, - amount=100, + amount=Decimal(100), denom="INJ", ) diff --git a/examples/chain_client/exchange/15_ExternalTransfer.py b/examples/chain_client/exchange/18_MsgExternalTransfer.py similarity index 96% rename from examples/chain_client/exchange/15_ExternalTransfer.py rename to examples/chain_client/exchange/18_MsgExternalTransfer.py index 3200be34..2bcc86a1 100644 --- a/examples/chain_client/exchange/15_ExternalTransfer.py +++ b/examples/chain_client/exchange/18_MsgExternalTransfer.py @@ -1,5 +1,6 @@ import asyncio import os +from decimal import Decimal import dotenv from grpc import RpcError @@ -32,11 +33,11 @@ async def main() -> None: dest_subaccount_id = "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000" # prepare tx msg - msg = composer.MsgExternalTransfer( + msg = composer.msg_external_transfer( sender=address.to_acc_bech32(), source_subaccount_id=subaccount_id, destination_subaccount_id=dest_subaccount_id, - amount=100, + amount=Decimal(100), denom="INJ", ) diff --git a/examples/chain_client/exchange/19_MsgLiquidatePosition.py b/examples/chain_client/exchange/19_MsgLiquidatePosition.py index d80ba385..9788b865 100644 --- a/examples/chain_client/exchange/19_MsgLiquidatePosition.py +++ b/examples/chain_client/exchange/19_MsgLiquidatePosition.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,19 +37,21 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" cid = str(uuid.uuid4()) - order = composer.DerivativeOrder( + order = composer.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=39.01, # This should be the liquidation price - quantity=0.147, - leverage=1, + price=Decimal(39.01), # This should be the liquidation price + quantity=Decimal(0.147), + margin=composer.calculate_margin( + quantity=Decimal(0.147), price=Decimal(39.01), leverage=Decimal(1), is_reduce_only=False + ), + order_type="SELL", cid=cid, - is_buy=False, ) # prepare tx msg - msg = composer.MsgLiquidatePosition( + msg = composer.msg_liquidate_position( sender=address.to_acc_bech32(), subaccount_id="0x156df4d5bc8e7dd9191433e54bd6a11eeb390921000000000000000000000000", market_id=market_id, diff --git a/examples/chain_client/exchange/1_MsgDeposit.py b/examples/chain_client/exchange/1_MsgDeposit.py index 80b9f652..bbf64710 100644 --- a/examples/chain_client/exchange/1_MsgDeposit.py +++ b/examples/chain_client/exchange/1_MsgDeposit.py @@ -31,7 +31,9 @@ async def main() -> None: subaccount_id = address.get_subaccount_id(index=0) # prepare tx msg - msg = composer.MsgDeposit(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=0.000001, denom="INJ") + msg = composer.msg_deposit( + sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=0.000001, denom="INJ" + ) # build sim tx tx = ( diff --git a/examples/chain_client/13_MsgIncreasePositionMargin.py b/examples/chain_client/exchange/20_MsgIncreasePositionMargin.py similarity index 96% rename from examples/chain_client/13_MsgIncreasePositionMargin.py rename to examples/chain_client/exchange/20_MsgIncreasePositionMargin.py index 775a41e5..276276e7 100644 --- a/examples/chain_client/13_MsgIncreasePositionMargin.py +++ b/examples/chain_client/exchange/20_MsgIncreasePositionMargin.py @@ -1,5 +1,6 @@ import asyncio import os +from decimal import Decimal import dotenv from grpc import RpcError @@ -34,12 +35,12 @@ async def main() -> None: market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" # prepare tx msg - msg = composer.MsgIncreasePositionMargin( + msg = composer.msg_increase_position_margin( sender=address.to_acc_bech32(), market_id=market_id, source_subaccount_id=subaccount_id, destination_subaccount_id=subaccount_id, - amount=2, + amount=Decimal(2), ) # build sim tx diff --git a/examples/chain_client/exchange/12_MsgRewardsOptOut.py b/examples/chain_client/exchange/21_MsgRewardsOptOut.py similarity index 97% rename from examples/chain_client/exchange/12_MsgRewardsOptOut.py rename to examples/chain_client/exchange/21_MsgRewardsOptOut.py index 8beaa1f4..2306b541 100644 --- a/examples/chain_client/exchange/12_MsgRewardsOptOut.py +++ b/examples/chain_client/exchange/21_MsgRewardsOptOut.py @@ -30,7 +30,7 @@ async def main() -> None: await client.fetch_account(address.to_acc_bech32()) # prepare tx msg - msg = composer.MsgRewardsOptOut(sender=address.to_acc_bech32()) + msg = composer.msg_rewards_opt_out(sender=address.to_acc_bech32()) # build sim tx tx = ( diff --git a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py b/examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py similarity index 96% rename from examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py rename to examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py index 0f39dcdb..b638b28a 100644 --- a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py +++ b/examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py @@ -1,5 +1,6 @@ import asyncio import os +from decimal import Decimal import dotenv from grpc import RpcError @@ -32,12 +33,12 @@ async def main() -> None: # prepare trade info market_id = "0xfafec40a7b93331c1fc89c23f66d11fbb48f38dfdd78f7f4fc4031fad90f6896" status = "Demolished" - settlement_price = 1 + settlement_price = Decimal(1) expiration_timestamp = 1685460582 settlement_timestamp = 1690730982 # prepare tx msg - msg = composer.MsgAdminUpdateBinaryOptionsMarket( + msg = composer.msg_admin_update_binary_options_market( sender=address.to_acc_bech32(), market_id=market_id, settlement_price=settlement_price, diff --git a/examples/chain_client/exchange/9_MsgWithdraw.py b/examples/chain_client/exchange/2_MsgWithdraw.py similarity index 95% rename from examples/chain_client/exchange/9_MsgWithdraw.py rename to examples/chain_client/exchange/2_MsgWithdraw.py index b198c0aa..1070d28c 100644 --- a/examples/chain_client/exchange/9_MsgWithdraw.py +++ b/examples/chain_client/exchange/2_MsgWithdraw.py @@ -31,7 +31,7 @@ async def main() -> None: subaccount_id = address.get_subaccount_id(index=0) # prepare tx msg - msg = composer.MsgWithdraw(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom="USDT") + msg = composer.msg_withdraw(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom="USDT") # build sim tx tx = ( diff --git a/examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py b/examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py new file mode 100644 index 00000000..90a177ec --- /dev/null +++ b/examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py @@ -0,0 +1,54 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + await client.initialize_tokens_from_chain_denoms() + composer = await client.composer() + await client.sync_timeout_height() + + message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( + network=network, + private_key=configured_private_key, + ) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + message = composer.msg_instant_spot_market_launch( + sender=address.to_acc_bech32(), + ticker="INJ/USDC", + base_denom="INJ", + quote_denom="USDC", + min_price_tick_size=Decimal("0.001"), + min_quantity_tick_size=Decimal("0.01"), + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py b/examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py new file mode 100644 index 00000000..b2b5dff4 --- /dev/null +++ b/examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py @@ -0,0 +1,61 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + await client.initialize_tokens_from_chain_denoms() + composer = await client.composer() + await client.sync_timeout_height() + + message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( + network=network, + private_key=configured_private_key, + ) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + message = composer.msg_instant_perpetual_market_launch( + sender=address.to_acc_bech32(), + ticker="INJ/USDC PERP", + quote_denom="USDC", + oracle_base="INJ", + oracle_quote="USDC", + oracle_scale_factor=6, + oracle_type="Band", + maker_fee_rate=Decimal("-0.0001"), + taker_fee_rate=Decimal("0.001"), + initial_margin_ratio=Decimal("0.33"), + maintenance_margin_ratio=Decimal("0.095"), + min_price_tick_size=Decimal("0.001"), + min_quantity_tick_size=Decimal("0.01"), + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py b/examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py new file mode 100644 index 00000000..d451fd15 --- /dev/null +++ b/examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py @@ -0,0 +1,62 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + await client.initialize_tokens_from_chain_denoms() + composer = await client.composer() + await client.sync_timeout_height() + + message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( + network=network, + private_key=configured_private_key, + ) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + message = composer.msg_instant_expiry_futures_market_launch( + sender=address.to_acc_bech32(), + ticker="INJ/USDC FUT", + quote_denom="USDC", + oracle_base="INJ", + oracle_quote="USDC", + oracle_scale_factor=6, + oracle_type="Band", + expiry=2000000000, + maker_fee_rate=Decimal("-0.0001"), + taker_fee_rate=Decimal("0.001"), + initial_margin_ratio=Decimal("0.33"), + maintenance_margin_ratio=Decimal("0.095"), + min_price_tick_size=Decimal("0.001"), + min_quantity_tick_size=Decimal("0.01"), + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py similarity index 94% rename from examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py rename to examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py index d3ca5f16..5b3b966a 100644 --- a/examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py +++ b/examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -37,15 +38,14 @@ async def main() -> None: cid = str(uuid.uuid4()) # prepare tx msg - msg = composer.MsgCreateSpotLimitOrder( + msg = composer.msg_create_spot_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=cid, ) diff --git a/examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py similarity index 94% rename from examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py rename to examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py index 5229632f..36ea27de 100644 --- a/examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py +++ b/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,14 +37,14 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateSpotMarketOrder( - sender=address.to_acc_bech32(), + msg = composer.msg_create_spot_market_order( market_id=market_id, + sender=address.to_acc_bech32(), subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=10.522, - quantity=0.01, - is_buy=True, + price=Decimal("10.522"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/exchange/5_MsgCancelSpotOrder.py b/examples/chain_client/exchange/8_MsgCancelSpotOrder.py similarity index 100% rename from examples/chain_client/exchange/5_MsgCancelSpotOrder.py rename to examples/chain_client/exchange/8_MsgCancelSpotOrder.py diff --git a/examples/chain_client/exchange/11_MsgBatchUpdateOrders.py b/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py similarity index 83% rename from examples/chain_client/exchange/11_MsgBatchUpdateOrders.py rename to examples/chain_client/exchange/9_MsgBatchUpdateOrders.py index 9efdc0a0..04e41058 100644 --- a/examples/chain_client/exchange/11_MsgBatchUpdateOrders.py +++ b/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -43,12 +44,12 @@ async def main() -> None: spot_market_id_cancel_2 = "0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0" derivative_orders_to_cancel = [ - composer.OrderData( + composer.order_data( market_id=derivative_market_id_cancel, subaccount_id=subaccount_id, order_hash="0x48690013c382d5dbaff9989db04629a16a5818d7524e027d517ccc89fd068103", ), - composer.OrderData( + composer.order_data( market_id=derivative_market_id_cancel_2, subaccount_id=subaccount_id, order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -56,12 +57,12 @@ async def main() -> None: ] spot_orders_to_cancel = [ - composer.OrderData( + composer.order_data( market_id=spot_market_id_cancel, subaccount_id=subaccount_id, cid="0e5c3ad5-2cc4-4a2a-bbe5-b12697739163", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id_cancel_2, subaccount_id=subaccount_id, order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", @@ -69,49 +70,49 @@ async def main() -> None: ] derivative_orders_to_create = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=derivative_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=25000, - quantity=0.1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(25000), + quantity=Decimal(0.1), + margin=composer.calculate_margin( + quantity=Decimal(0.1), price=Decimal(25000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.DerivativeOrder( + composer.derivative_order( market_id=derivative_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=50000, - quantity=0.01, - leverage=1, - is_buy=False, - is_po=False, + price=Decimal(50000), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ), ] spot_orders_to_create = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=3, - quantity=55, - is_buy=True, - is_po=False, + price=Decimal("3"), + quantity=Decimal("55"), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=300, - quantity=55, - is_buy=False, - is_po=False, + price=Decimal("300"), + quantity=Decimal("55"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] diff --git a/examples/chain_client/41_MsgCreateInsuranceFund.py b/examples/chain_client/insurance/1_MsgCreateInsuranceFund.py similarity index 100% rename from examples/chain_client/41_MsgCreateInsuranceFund.py rename to examples/chain_client/insurance/1_MsgCreateInsuranceFund.py diff --git a/examples/chain_client/42_MsgUnderwrite.py b/examples/chain_client/insurance/2_MsgUnderwrite.py similarity index 100% rename from examples/chain_client/42_MsgUnderwrite.py rename to examples/chain_client/insurance/2_MsgUnderwrite.py diff --git a/examples/chain_client/43_MsgRequestRedemption.py b/examples/chain_client/insurance/3_MsgRequestRedemption.py similarity index 100% rename from examples/chain_client/43_MsgRequestRedemption.py rename to examples/chain_client/insurance/3_MsgRequestRedemption.py diff --git a/examples/chain_client/23_MsgRelayPriceFeedPrice.py b/examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py similarity index 100% rename from examples/chain_client/23_MsgRelayPriceFeedPrice.py rename to examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py diff --git a/examples/chain_client/36_MsgRelayProviderPrices.py b/examples/chain_client/oracle/2_MsgRelayProviderPrices.py similarity index 100% rename from examples/chain_client/36_MsgRelayProviderPrices.py rename to examples/chain_client/oracle/2_MsgRelayProviderPrices.py diff --git a/examples/chain_client/22_MsgSendToEth.py b/examples/chain_client/peggy/1_MsgSendToEth.py similarity index 100% rename from examples/chain_client/22_MsgSendToEth.py rename to examples/chain_client/peggy/1_MsgSendToEth.py diff --git a/examples/chain_client/25_MsgDelegate.py b/examples/chain_client/staking/1_MsgDelegate.py similarity index 100% rename from examples/chain_client/25_MsgDelegate.py rename to examples/chain_client/staking/1_MsgDelegate.py diff --git a/examples/chain_client/71_CreateDenom.py b/examples/chain_client/tokenfactory/1_CreateDenom.py similarity index 100% rename from examples/chain_client/71_CreateDenom.py rename to examples/chain_client/tokenfactory/1_CreateDenom.py diff --git a/examples/chain_client/72_MsgMint.py b/examples/chain_client/tokenfactory/2_MsgMint.py similarity index 100% rename from examples/chain_client/72_MsgMint.py rename to examples/chain_client/tokenfactory/2_MsgMint.py diff --git a/examples/chain_client/73_MsgBurn.py b/examples/chain_client/tokenfactory/3_MsgBurn.py similarity index 100% rename from examples/chain_client/73_MsgBurn.py rename to examples/chain_client/tokenfactory/3_MsgBurn.py diff --git a/examples/chain_client/75_MsgChangeAdmin.py b/examples/chain_client/tokenfactory/4_MsgChangeAdmin.py similarity index 100% rename from examples/chain_client/75_MsgChangeAdmin.py rename to examples/chain_client/tokenfactory/4_MsgChangeAdmin.py diff --git a/examples/chain_client/74_MsgSetDenomMetadata.py b/examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py similarity index 100% rename from examples/chain_client/74_MsgSetDenomMetadata.py rename to examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py diff --git a/examples/chain_client/68_DenomAuthorityMetadata.py b/examples/chain_client/tokenfactory/query/1_DenomAuthorityMetadata.py similarity index 100% rename from examples/chain_client/68_DenomAuthorityMetadata.py rename to examples/chain_client/tokenfactory/query/1_DenomAuthorityMetadata.py diff --git a/examples/chain_client/69_DenomsFromCreator.py b/examples/chain_client/tokenfactory/query/2_DenomsFromCreator.py similarity index 100% rename from examples/chain_client/69_DenomsFromCreator.py rename to examples/chain_client/tokenfactory/query/2_DenomsFromCreator.py diff --git a/examples/chain_client/70_TokenfactoryModuleState.py b/examples/chain_client/tokenfactory/query/3_TokenfactoryModuleState.py similarity index 100% rename from examples/chain_client/70_TokenfactoryModuleState.py rename to examples/chain_client/tokenfactory/query/3_TokenfactoryModuleState.py diff --git a/examples/chain_client/37_GetTx.py b/examples/chain_client/tx/query/1_GetTx.py similarity index 100% rename from examples/chain_client/37_GetTx.py rename to examples/chain_client/tx/query/1_GetTx.py diff --git a/examples/chain_client/40_MsgExecuteContract.py b/examples/chain_client/wasm/1_MsgExecuteContract.py similarity index 100% rename from examples/chain_client/40_MsgExecuteContract.py rename to examples/chain_client/wasm/1_MsgExecuteContract.py diff --git a/examples/chain_client/67_ContractsByCreator.py b/examples/chain_client/wasm/query/10_ContractsByCreator.py similarity index 100% rename from examples/chain_client/67_ContractsByCreator.py rename to examples/chain_client/wasm/query/10_ContractsByCreator.py diff --git a/examples/chain_client/58_ContractInfo.py b/examples/chain_client/wasm/query/1_ContractInfo.py similarity index 100% rename from examples/chain_client/58_ContractInfo.py rename to examples/chain_client/wasm/query/1_ContractInfo.py diff --git a/examples/chain_client/59_ContractHistory.py b/examples/chain_client/wasm/query/2_ContractHistory.py similarity index 100% rename from examples/chain_client/59_ContractHistory.py rename to examples/chain_client/wasm/query/2_ContractHistory.py diff --git a/examples/chain_client/60_ContractsByCode.py b/examples/chain_client/wasm/query/3_ContractsByCode.py similarity index 100% rename from examples/chain_client/60_ContractsByCode.py rename to examples/chain_client/wasm/query/3_ContractsByCode.py diff --git a/examples/chain_client/61_AllContractsState.py b/examples/chain_client/wasm/query/4_AllContractsState.py similarity index 100% rename from examples/chain_client/61_AllContractsState.py rename to examples/chain_client/wasm/query/4_AllContractsState.py diff --git a/examples/chain_client/62_RawContractState.py b/examples/chain_client/wasm/query/5_RawContractState.py similarity index 100% rename from examples/chain_client/62_RawContractState.py rename to examples/chain_client/wasm/query/5_RawContractState.py diff --git a/examples/chain_client/63_SmartContractState.py b/examples/chain_client/wasm/query/6_SmartContractState.py similarity index 100% rename from examples/chain_client/63_SmartContractState.py rename to examples/chain_client/wasm/query/6_SmartContractState.py diff --git a/examples/chain_client/64_SmartContractCode.py b/examples/chain_client/wasm/query/7_SmartContractCode.py similarity index 100% rename from examples/chain_client/64_SmartContractCode.py rename to examples/chain_client/wasm/query/7_SmartContractCode.py diff --git a/examples/chain_client/65_SmartContractCodes.py b/examples/chain_client/wasm/query/8_SmartContractCodes.py similarity index 100% rename from examples/chain_client/65_SmartContractCodes.py rename to examples/chain_client/wasm/query/8_SmartContractCodes.py diff --git a/examples/chain_client/66_SmartContractPinnedCodes.py b/examples/chain_client/wasm/query/9_SmartContractPinnedCodes.py similarity index 100% rename from examples/chain_client/66_SmartContractPinnedCodes.py rename to examples/chain_client/wasm/query/9_SmartContractPinnedCodes.py diff --git a/pyinjective/composer.py b/pyinjective/composer.py index df353d6b..9a0807c9 100644 --- a/pyinjective/composer.py +++ b/pyinjective/composer.py @@ -13,7 +13,7 @@ from pyinjective.core.token import Token from pyinjective.proto.cosmos.authz.v1beta1 import authz_pb2 as cosmos_authz_pb, tx_pb2 as cosmos_authz_tx_pb from pyinjective.proto.cosmos.bank.v1beta1 import bank_pb2 as bank_pb, tx_pb2 as cosmos_bank_tx_pb -from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as cosmos_dot_base_dot_v1beta1_dot_coin__pb2 +from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as base_coin_pb from pyinjective.proto.cosmos.distribution.v1beta1 import ( distribution_pb2 as cosmos_distribution_pb2, tx_pb2 as cosmos_distribution_tx_pb, @@ -25,15 +25,19 @@ from pyinjective.proto.injective.auction.v1beta1 import tx_pb2 as injective_auction_tx_pb from pyinjective.proto.injective.exchange.v1beta1 import ( authz_pb2 as injective_authz_pb, - exchange_pb2 as injective_dot_exchange_dot_v1beta1_dot_exchange__pb2, + exchange_pb2 as injective_exchange_pb, tx_pb2 as injective_exchange_tx_pb, ) from pyinjective.proto.injective.insurance.v1beta1 import tx_pb2 as injective_insurance_tx_pb -from pyinjective.proto.injective.oracle.v1beta1 import tx_pb2 as injective_oracle_tx_pb +from pyinjective.proto.injective.oracle.v1beta1 import ( + oracle_pb2 as injective_oracle_pb, + tx_pb2 as injective_oracle_tx_pb, +) from pyinjective.proto.injective.peggy.v1 import msgs_pb2 as injective_peggy_tx_pb from pyinjective.proto.injective.stream.v1beta1 import query_pb2 as chain_stream_query from pyinjective.proto.injective.tokenfactory.v1beta1 import tx_pb2 as token_factory_tx_pb from pyinjective.proto.injective.wasmx.v1 import tx_pb2 as wasmx_tx_pb +from pyinjective.utils.denom import Denom REQUEST_TO_RESPONSE_TYPE_MAP = { "MsgCreateSpotLimitOrder": injective_exchange_tx_pb.MsgCreateSpotLimitOrderResponse, @@ -137,14 +141,14 @@ def Coin(self, amount: int, denom: str): This method is deprecated and will be removed soon. Please use `coin` instead """ warn("This method is deprecated. Use coin instead", DeprecationWarning, stacklevel=2) - return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=str(amount), denom=denom) + return base_coin_pb.Coin(amount=str(amount), denom=denom) def coin(self, amount: int, denom: str): """ This method create an instance of Coin gRPC type, considering the amount is already expressed in chain format """ formatted_amount_string = str(int(amount)) - return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=formatted_amount_string, denom=denom) + return base_coin_pb.Coin(amount=formatted_amount_string, denom=denom) def create_coin_amount(self, amount: Decimal, token_name: str): """ @@ -154,35 +158,38 @@ def create_coin_amount(self, amount: Decimal, token_name: str): chain_amount = token.chain_formatted_value(human_readable_value=amount) return self.coin(amount=int(chain_amount), denom=token.denom) - def get_order_mask(self, **kwargs): - order_mask = 0 - - if kwargs.get("is_conditional"): - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.CONDITIONAL - else: - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.REGULAR - - if kwargs.get("order_direction") == "buy": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.DIRECTION_BUY_OR_HIGHER - - elif kwargs.get("order_direction") == "sell": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.DIRECTION_SELL_OR_LOWER - - if kwargs.get("order_type") == "market": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.TYPE_MARKET - - elif kwargs.get("order_type") == "limit": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.TYPE_LIMIT - - if order_mask == 0: - order_mask = 1 - - return order_mask - def OrderData( self, market_id: str, subaccount_id: str, order_hash: Optional[str] = None, cid: Optional[str] = None, **kwargs ): - order_mask = self.get_order_mask(**kwargs) + """ + This method is deprecated and will be removed soon. Please use `order_data` instead + """ + warn("This method is deprecated. Use order_data instead", DeprecationWarning, stacklevel=2) + + is_conditional = kwargs.get("is_conditional", False) + is_buy = kwargs.get("order_direction", "buy") == "buy" + is_market_order = kwargs.get("order_type", "limit") == "market" + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) + + return injective_exchange_tx_pb.OrderData( + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + order_mask=order_mask, + cid=cid, + ) + + def order_data( + self, + market_id: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + is_conditional: Optional[bool] = False, + is_buy: Optional[bool] = False, + is_market_order: Optional[bool] = False, + ) -> injective_exchange_tx_pb.OrderData: + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) return injective_exchange_tx_pb.OrderData( market_id=market_id, @@ -202,6 +209,11 @@ def SpotOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `spot_order` instead + """ + warn("This method is deprecated. Use spot_order instead", DeprecationWarning, stacklevel=2) + market = self.spot_markets[market_id] # prepare values @@ -210,20 +222,20 @@ def SpotOrder( trigger_price = market.price_to_chain_format(human_readable_value=Decimal(0)) if kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY + order_type = injective_exchange_pb.OrderType.BUY elif not kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL + order_type = injective_exchange_pb.OrderType.SELL elif kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY_PO + order_type = injective_exchange_pb.OrderType.BUY_PO elif not kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL_PO + order_type = injective_exchange_pb.OrderType.SELL_PO - return injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.SpotOrder( + return injective_exchange_pb.SpotOrder( market_id=market_id, - order_info=injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderInfo( + order_info=injective_exchange_pb.OrderInfo( subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=str(int(price)), @@ -234,6 +246,50 @@ def SpotOrder( trigger_price=str(int(trigger_price)), ) + def spot_order( + self, + market_id: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_pb.SpotOrder: + market = self.spot_markets[market_id] + + chain_quantity = f"{market.quantity_to_chain_format(human_readable_value=quantity).normalize():f}" + chain_price = f"{market.price_to_chain_format(human_readable_value=price).normalize():f}" + + trigger_price = trigger_price or Decimal(0) + chain_trigger_price = f"{market.price_to_chain_format(human_readable_value=trigger_price).normalize():f}" + + chain_order_type = injective_exchange_pb.OrderType.Value(order_type) + + return injective_exchange_pb.SpotOrder( + market_id=market_id, + order_info=injective_exchange_pb.OrderInfo( + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=chain_price, + quantity=chain_quantity, + cid=cid, + ), + order_type=chain_order_type, + trigger_price=chain_trigger_price, + ) + + def calculate_margin( + self, quantity: Decimal, price: Decimal, leverage: Decimal, is_reduce_only: bool = False + ) -> Decimal: + if is_reduce_only: + margin = Decimal(0) + else: + margin = quantity * price / leverage + + return margin + def DerivativeOrder( self, market_id: str, @@ -245,6 +301,10 @@ def DerivativeOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `derivative_order` instead + """ + warn("This method is deprecated. Use derivative_order instead", DeprecationWarning, stacklevel=2) market = self.derivative_markets[market_id] if kwargs.get("is_reduce_only", False): @@ -262,32 +322,32 @@ def DerivativeOrder( trigger_price = market.price_to_chain_format(human_readable_value=Decimal(str(trigger_price))) if kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY + order_type = injective_exchange_pb.OrderType.BUY elif not kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL + order_type = injective_exchange_pb.OrderType.SELL elif kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY_PO + order_type = injective_exchange_pb.OrderType.BUY_PO elif not kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL_PO + order_type = injective_exchange_pb.OrderType.SELL_PO elif kwargs.get("stop_buy"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.STOP_BUY + order_type = injective_exchange_pb.OrderType.STOP_BUY elif kwargs.get("stop_sell"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.STOP_SEll + order_type = injective_exchange_pb.OrderType.STOP_SEll elif kwargs.get("take_buy"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.TAKE_BUY + order_type = injective_exchange_pb.OrderType.TAKE_BUY elif kwargs.get("take_sell"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.TAKE_SELL + order_type = injective_exchange_pb.OrderType.TAKE_SELL - return injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.DerivativeOrder( + return injective_exchange_pb.DerivativeOrder( market_id=market_id, - order_info=injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderInfo( + order_info=injective_exchange_pb.OrderInfo( subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=str(int(price)), @@ -299,60 +359,121 @@ def DerivativeOrder( trigger_price=str(int(trigger_price)), ) - def BinaryOptionsOrder( + def derivative_order( self, market_id: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, cid: Optional[str] = None, - **kwargs, - ): - market = self.binary_option_markets[market_id] - denom = kwargs.get("denom", None) + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_pb.DerivativeOrder: + market = self.derivative_markets[market_id] - if kwargs.get("is_reduce_only", False): - margin = 0 - else: - margin = market.calculate_margin_in_chain_format( - human_readable_quantity=Decimal(str(quantity)), - human_readable_price=Decimal(str(price)), - is_buy=kwargs["is_buy"], - special_denom=denom, - ) + chain_quantity = market.quantity_to_chain_format(human_readable_value=quantity) + chain_price = market.price_to_chain_format(human_readable_value=price) + chain_margin = market.margin_to_chain_format(human_readable_value=margin) - # prepare values - price = market.price_to_chain_format(human_readable_value=Decimal(str(price)), special_denom=denom) - trigger_price = market.price_to_chain_format(human_readable_value=Decimal(str(0)), special_denom=denom) - quantity = market.quantity_to_chain_format(human_readable_value=Decimal(str(quantity)), special_denom=denom) + trigger_price = trigger_price or Decimal(0) + chain_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price) - if kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY + return self._basic_derivative_order( + market_id=market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + chain_price=chain_price, + chain_quantity=chain_quantity, + chain_margin=chain_margin, + order_type=order_type, + cid=cid, + chain_trigger_price=chain_trigger_price, + ) - elif not kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL + def binary_options_order( + self, + market_id: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + denom: Optional[Denom] = None, + ) -> injective_exchange_pb.DerivativeOrder: + market = self.binary_option_markets[market_id] - elif kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY_PO + chain_quantity = market.quantity_to_chain_format(human_readable_value=quantity, special_denom=denom) + chain_price = market.price_to_chain_format(human_readable_value=price, special_denom=denom) + chain_margin = market.margin_to_chain_format(human_readable_value=margin, special_denom=denom) - elif not kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL_PO + trigger_price = trigger_price or Decimal(0) + chain_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price, special_denom=denom) - return injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.DerivativeOrder( - market_id=market_id, - order_info=injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderInfo( - subaccount_id=subaccount_id, - fee_recipient=fee_recipient, - price=str(int(price)), - quantity=str(int(quantity)), - cid=cid, - ), - margin=str(int(margin)), + return self._basic_derivative_order( + market_id=market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + chain_price=chain_price, + chain_quantity=chain_quantity, + chain_margin=chain_margin, order_type=order_type, - trigger_price=str(int(trigger_price)), + cid=cid, + chain_trigger_price=chain_trigger_price, + ) + + # region Auction module + def MsgBid(self, sender: str, bid_amount: float, round: float): + be_amount = Decimal(str(bid_amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_auction_tx_pb.MsgBid( + sender=sender, + round=round, + bid_amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), + ) + + # endregion + + # region Authz module + def MsgGrantGeneric(self, granter: str, grantee: str, msg_type: str, expire_in: int): + auth = cosmos_authz_pb.GenericAuthorization(msg=msg_type) + any_auth = any_pb2.Any() + any_auth.Pack(auth, type_url_prefix="") + + grant = cosmos_authz_pb.Grant( + authorization=any_auth, + expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), + ) + + return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + + def MsgExec(self, grantee: str, msgs: List): + any_msgs: List[any_pb2.Any] = [] + for msg in msgs: + any_msg = any_pb2.Any() + any_msg.Pack(msg, type_url_prefix="") + any_msgs.append(any_msg) + + return cosmos_authz_tx_pb.MsgExec(grantee=grantee, msgs=any_msgs) + + def MsgRevoke(self, granter: str, grantee: str, msg_type: str): + return cosmos_authz_tx_pb.MsgRevoke(granter=granter, grantee=grantee, msg_type_url=msg_type) + + def msg_execute_contract_compat(self, sender: str, contract: str, msg: str, funds: str): + return wasmx_tx_pb.MsgExecuteContractCompat( + sender=sender, + contract=contract, + msg=msg, + funds=funds, ) + # endregion + + # region Bank module def MsgSend(self, from_address: str, to_address: str, amount: float, denom: str): coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) @@ -362,16 +483,14 @@ def MsgSend(self, from_address: str, to_address: str, amount: float, denom: str) amount=[coin], ) - def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): - return wasm_tx_pb.MsgExecuteContract( - sender=sender, - contract=contract, - msg=bytes(msg, "utf-8"), - funds=kwargs.get("funds") # funds is a list of cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin. - # The coins in the list must be sorted in alphabetical order by denoms. - ) + # endregion + # region Chain Exchange module def MsgDeposit(self, sender: str, subaccount_id: str, amount: float, denom: str): + """ + This method is deprecated and will be removed soon. Please use `msg_deposit` instead + """ + warn("This method is deprecated. Use msg_deposit instead", DeprecationWarning, stacklevel=2) coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgDeposit( @@ -380,6 +499,153 @@ def MsgDeposit(self, sender: str, subaccount_id: str, amount: float, denom: str) amount=coin, ) + def msg_deposit(self, sender: str, subaccount_id: str, amount: Decimal, denom: str): + coin = self.create_coin_amount(amount=amount, token_name=denom) + + return injective_exchange_tx_pb.MsgDeposit( + sender=sender, + subaccount_id=subaccount_id, + amount=coin, + ) + + def MsgWithdraw(self, sender: str, subaccount_id: str, amount: float, denom: str): + """ + This method is deprecated and will be removed soon. Please use `msg_withdraw` instead + """ + warn("This method is deprecated. Use msg_withdraw instead", DeprecationWarning, stacklevel=2) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + + return injective_exchange_tx_pb.MsgWithdraw( + sender=sender, + subaccount_id=subaccount_id, + amount=be_amount, + ) + + def msg_withdraw(self, sender: str, subaccount_id: str, amount: Decimal, denom: str): + be_amount = self.create_coin_amount(amount=amount, token_name=denom) + + return injective_exchange_tx_pb.MsgWithdraw( + sender=sender, + subaccount_id=subaccount_id, + amount=be_amount, + ) + + def msg_instant_spot_market_launch( + self, + sender: str, + ticker: str, + base_denom: str, + quote_denom: str, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantSpotMarketLaunch: + base_token = self.tokens[base_denom] + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals - base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal( + f"1e{base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + + return injective_exchange_tx_pb.MsgInstantSpotMarketLaunch( + sender=sender, + ticker=ticker, + base_denom=base_token.denom, + quote_denom=quote_token.denom, + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", + ) + + def msg_instant_perpetual_market_launch( + self, + sender: str, + ticker: str, + quote_denom: str, + oracle_base: str, + oracle_quote: str, + oracle_scale_factor: int, + oracle_type: str, + maker_fee_rate: Decimal, + taker_fee_rate: Decimal, + initial_margin_ratio: Decimal, + maintenance_margin_ratio: Decimal, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch: + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch( + sender=sender, + ticker=ticker, + quote_denom=quote_token.denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=injective_oracle_pb.OracleType.Value(oracle_type), + maker_fee_rate=f"{chain_maker_fee_rate.normalize():f}", + taker_fee_rate=f"{chain_taker_fee_rate.normalize():f}", + initial_margin_ratio=f"{chain_initial_margin_ratio.normalize():f}", + maintenance_margin_ratio=f"{chain_maintenance_margin_ratio.normalize():f}", + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", + ) + + def msg_instant_expiry_futures_market_launch( + self, + sender: str, + ticker: str, + quote_denom: str, + oracle_base: str, + oracle_quote: str, + oracle_scale_factor: int, + oracle_type: str, + expiry: int, + maker_fee_rate: Decimal, + taker_fee_rate: Decimal, + initial_margin_ratio: Decimal, + maintenance_margin_ratio: Decimal, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch: + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_exchange_tx_pb.MsgInstantExpiryFuturesMarketLaunch( + sender=sender, + ticker=ticker, + quote_denom=quote_token.denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=injective_oracle_pb.OracleType.Value(oracle_type), + expiry=expiry, + maker_fee_rate=f"{chain_maker_fee_rate.normalize():f}", + taker_fee_rate=f"{chain_taker_fee_rate.normalize():f}", + initial_margin_ratio=f"{chain_initial_margin_ratio.normalize():f}", + maintenance_margin_ratio=f"{chain_maintenance_margin_ratio.normalize():f}", + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", + ) + def MsgCreateSpotLimitOrder( self, market_id: str, @@ -391,52 +657,151 @@ def MsgCreateSpotLimitOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `msg_create_spot_limit_order` instead + """ + warn("This method is deprecated. Use msg_create_spot_limit_order instead", DeprecationWarning, stacklevel=2) + + order_type_name = "BUY" + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + return injective_exchange_tx_pb.MsgCreateSpotLimitOrder( sender=sender, - order=self.SpotOrder( + order=self.spot_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=price, - quantity=quantity, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + order_type=order_type_name, cid=cid, - **kwargs, ), ) - def MsgCreateSpotMarketOrder( + def msg_create_spot_limit_order( self, market_id: str, sender: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, - is_buy: bool, + price: Decimal, + quantity: Decimal, + order_type: str, cid: Optional[str] = None, - ): - return injective_exchange_tx_pb.MsgCreateSpotMarketOrder( + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateSpotLimitOrder: + return injective_exchange_tx_pb.MsgCreateSpotLimitOrder( sender=sender, - order=self.SpotOrder( + order=self.spot_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=price, quantity=quantity, - is_buy=is_buy, + order_type=order_type, cid=cid, + trigger_price=trigger_price, ), ) - def MsgCancelSpotOrder( + def MsgBatchCreateSpotLimitOrders(self, sender: str, orders: List): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_create_spot_limit_orders` instead + """ + warn( + "This method is deprecated. Use msg_batch_create_spot_limit_orders instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders(sender=sender, orders=orders) + + def msg_batch_create_spot_limit_orders( + self, sender: str, orders: List[injective_exchange_pb.SpotOrder] + ) -> injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders: + return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders(sender=sender, orders=orders) + + def MsgCreateSpotMarketOrder( self, market_id: str, sender: str, subaccount_id: str, - order_hash: Optional[str] = None, + fee_recipient: str, + price: float, + quantity: float, + is_buy: bool, cid: Optional[str] = None, ): - return injective_exchange_tx_pb.MsgCancelSpotOrder( + """ + This method is deprecated and will be removed soon. Please use `msg_create_spot_market_order` instead + """ + warn("This method is deprecated. Use msg_create_spot_market_order instead", DeprecationWarning, stacklevel=2) + + order_type_name = "BUY" + if not is_buy: + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + return injective_exchange_tx_pb.MsgCreateSpotMarketOrder( + sender=sender, + order=self.spot_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + order_type=order_type_name, + cid=cid, + ), + ) + + def msg_create_spot_market_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateSpotMarketOrder: + return injective_exchange_tx_pb.MsgCreateSpotMarketOrder( + sender=sender, + order=self.spot_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ), + ) + + def MsgCancelSpotOrder( + self, + market_id: str, + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_cancel_spot_order` instead + """ + warn("This method is deprecated. Use msg_cancel_spot_order instead", DeprecationWarning, stacklevel=2) + return injective_exchange_tx_pb.MsgCancelSpotOrder( sender=sender, market_id=market_id, subaccount_id=subaccount_id, @@ -444,14 +809,111 @@ def MsgCancelSpotOrder( cid=cid, ) - def MsgBatchCreateSpotLimitOrders(self, sender: str, orders: List): - return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders(sender=sender, orders=orders) + def msg_cancel_spot_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + ) -> injective_exchange_tx_pb.MsgCancelSpotOrder: + return injective_exchange_tx_pb.MsgCancelSpotOrder( + sender=sender, + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + ) def MsgBatchCancelSpotOrders(self, sender: str, data: List): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_cancel_spot_orders` instead + """ + warn("This method is deprecated. Use msg_batch_cancel_spot_orders instead", DeprecationWarning, stacklevel=2) return injective_exchange_tx_pb.MsgBatchCancelSpotOrders(sender=sender, data=data) - def MsgRewardsOptOut(self, sender: str): - return injective_exchange_tx_pb.MsgRewardsOptOut(sender=sender) + def msg_batch_cancel_spot_orders( + self, sender: str, orders_data: List[injective_exchange_tx_pb.OrderData] + ) -> injective_exchange_tx_pb.MsgBatchCancelSpotOrders: + return injective_exchange_tx_pb.MsgBatchCancelSpotOrders(sender=sender, data=orders_data) + + def MsgBatchUpdateOrders(self, sender: str, **kwargs): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_update_orders` instead + """ + warn("This method is deprecated. Use msg_batch_update_orders instead", DeprecationWarning, stacklevel=2) + return injective_exchange_tx_pb.MsgBatchUpdateOrders( + sender=sender, + subaccount_id=kwargs.get("subaccount_id"), + spot_market_ids_to_cancel_all=kwargs.get("spot_market_ids_to_cancel_all"), + derivative_market_ids_to_cancel_all=kwargs.get("derivative_market_ids_to_cancel_all"), + spot_orders_to_cancel=kwargs.get("spot_orders_to_cancel"), + derivative_orders_to_cancel=kwargs.get("derivative_orders_to_cancel"), + spot_orders_to_create=kwargs.get("spot_orders_to_create"), + derivative_orders_to_create=kwargs.get("derivative_orders_to_create"), + binary_options_orders_to_cancel=kwargs.get("binary_options_orders_to_cancel"), + binary_options_market_ids_to_cancel_all=kwargs.get("binary_options_market_ids_to_cancel_all"), + binary_options_orders_to_create=kwargs.get("binary_options_orders_to_create"), + ) + + def msg_batch_update_orders( + self, + sender: str, + subaccount_id: Optional[str] = None, + spot_market_ids_to_cancel_all: Optional[List[str]] = None, + derivative_market_ids_to_cancel_all: Optional[List[str]] = None, + spot_orders_to_cancel: Optional[List[injective_exchange_tx_pb.OrderData]] = None, + derivative_orders_to_cancel: Optional[List[injective_exchange_tx_pb.OrderData]] = None, + spot_orders_to_create: Optional[List[injective_exchange_pb.SpotOrder]] = None, + derivative_orders_to_create: Optional[List[injective_exchange_pb.DerivativeOrder]] = None, + binary_options_orders_to_cancel: Optional[List[injective_exchange_tx_pb.OrderData]] = None, + binary_options_market_ids_to_cancel_all: Optional[List[str]] = None, + binary_options_orders_to_create: Optional[List[injective_exchange_pb.DerivativeOrder]] = None, + ) -> injective_exchange_tx_pb.MsgBatchUpdateOrders: + return injective_exchange_tx_pb.MsgBatchUpdateOrders( + sender=sender, + subaccount_id=subaccount_id, + spot_market_ids_to_cancel_all=spot_market_ids_to_cancel_all, + derivative_market_ids_to_cancel_all=derivative_market_ids_to_cancel_all, + spot_orders_to_cancel=spot_orders_to_cancel, + derivative_orders_to_cancel=derivative_orders_to_cancel, + spot_orders_to_create=spot_orders_to_create, + derivative_orders_to_create=derivative_orders_to_create, + binary_options_orders_to_cancel=binary_options_orders_to_cancel, + binary_options_market_ids_to_cancel_all=binary_options_market_ids_to_cancel_all, + binary_options_orders_to_create=binary_options_orders_to_create, + ) + + def MsgPrivilegedExecuteContract( + self, sender: str, contract: str, msg: str, **kwargs + ) -> injective_exchange_tx_pb.MsgPrivilegedExecuteContract: + """ + This method is deprecated and will be removed soon. Please use `msg_privileged_execute_contract` instead + """ + warn("This method is deprecated. Use msg_privileged_execute_contract instead", DeprecationWarning, stacklevel=2) + + return injective_exchange_tx_pb.MsgPrivilegedExecuteContract( + sender=sender, + contract_address=contract, + data=msg, + funds=kwargs.get("funds") # funds is a string of Coin strings, comma separated, + # e.g. 100000inj,20000000000usdt + ) + + def msg_privileged_execute_contract( + self, + sender: str, + contract_address: str, + data: str, + funds: Optional[str] = None, + ) -> injective_exchange_tx_pb.MsgPrivilegedExecuteContract: + # funds is a string of Coin strings, comma separated, e.g. 100000inj,20000000000usdt + return injective_exchange_tx_pb.MsgPrivilegedExecuteContract( + sender=sender, + contract_address=contract_address, + data=data, + funds=funds, + ) def MsgCreateDerivativeLimitOrder( self, @@ -464,46 +926,105 @@ def MsgCreateDerivativeLimitOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `msg_create_derivative_limit_order` instead + """ + warn( + "This method is deprecated. Use msg_create_derivative_limit_order instead", DeprecationWarning, stacklevel=2 + ) + + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) / Decimal(str(kwargs["leverage"])) + + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + return injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder( sender=sender, - order=self.DerivativeOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=price, - quantity=quantity, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, ), ) - def MsgCreateDerivativeMarketOrder( + def msg_create_derivative_limit_order( self, market_id: str, sender: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, - is_buy: bool, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, cid: Optional[str] = None, - **kwargs, - ): - return injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder( + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder: + return injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder( sender=sender, - order=self.DerivativeOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=price, quantity=quantity, - is_buy=is_buy, + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=trigger_price, ), ) - def MsgCreateBinaryOptionsLimitOrder( + def MsgBatchCreateDerivativeLimitOrders(self, sender: str, orders: List): + """ + This method is deprecated and will be removed soon. + Please use `msg_batch_create_derivative_limit_orders` instead + """ + warn( + "This method is deprecated. Use msg_batch_create_derivative_limit_orders instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders(sender=sender, orders=orders) + + def msg_batch_create_derivative_limit_orders( + self, + sender: str, + orders: List[injective_exchange_pb.DerivativeOrder], + ) -> injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders: + return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders(sender=sender, orders=orders) + + def MsgCreateDerivativeMarketOrder( self, market_id: str, sender: str, @@ -514,95 +1035,156 @@ def MsgCreateBinaryOptionsLimitOrder( cid: Optional[str] = None, **kwargs, ): - return injective_exchange_tx_pb.MsgCreateBinaryOptionsLimitOrder( + """ + This method is deprecated and will be removed soon. Please use `msg_create_derivative_market_order` instead + """ + warn( + "This method is deprecated. Use msg_create_derivative_market_order instead", + DeprecationWarning, + stacklevel=2, + ) + + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) / Decimal(str(kwargs["leverage"])) + + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + + return injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder( sender=sender, - order=self.BinaryOptionsOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=price, - quantity=quantity, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, ), ) - def MsgCreateBinaryOptionsMarketOrder( + def msg_create_derivative_market_order( self, market_id: str, sender: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, cid: Optional[str] = None, - **kwargs, - ): - return injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder( + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder: + return injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder( sender=sender, - order=self.BinaryOptionsOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=price, quantity=quantity, + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=trigger_price, ), ) - def MsgCancelBinaryOptionsOrder( + def MsgCancelDerivativeOrder( self, - sender: str, market_id: str, + sender: str, subaccount_id: str, order_hash: Optional[str] = None, cid: Optional[str] = None, + **kwargs, ): - return injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder( + """ + This method is deprecated and will be removed soon. Please use `msg_cancel_derivative_order` instead + """ + warn( + "This method is deprecated. Use msg_cancel_derivative_order instead", + DeprecationWarning, + stacklevel=2, + ) + + is_conditional = kwargs.get("is_conditional", False) + is_buy = kwargs.get("order_direction", "buy") == "buy" + is_market_order = kwargs.get("order_type", "limit") == "market" + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) + + return injective_exchange_tx_pb.MsgCancelDerivativeOrder( sender=sender, market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash, + order_mask=order_mask, cid=cid, ) - def MsgAdminUpdateBinaryOptionsMarket( + def msg_cancel_derivative_order( self, - sender: str, market_id: str, - status: str, - **kwargs, - ): - price_to_bytes = None - - if kwargs.get("settlement_price") is not None: - scale_price = Decimal((kwargs.get("settlement_price") * pow(10, 18))) - price_to_bytes = bytes(str(scale_price), "utf-8") - - else: - price_to_bytes = "" + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + is_conditional: Optional[bool] = False, + is_buy: Optional[bool] = False, + is_market_order: Optional[bool] = False, + ) -> injective_exchange_tx_pb.MsgCancelDerivativeOrder: + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) - return injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket( + return injective_exchange_tx_pb.MsgCancelDerivativeOrder( sender=sender, market_id=market_id, - settlement_price=price_to_bytes, - expiration_timestamp=kwargs.get("expiration_timestamp"), - settlement_timestamp=kwargs.get("settlement_timestamp"), - status=status, + subaccount_id=subaccount_id, + order_hash=order_hash, + order_mask=order_mask, + cid=cid, ) - def MsgRelayProviderPrices(self, sender: str, provider: str, symbols: list, prices: list): - oracle_prices = [] - - for price in prices: - scale_price = Decimal((price) * pow(10, 18)) - price_to_bytes = bytes(str(scale_price), "utf-8") - oracle_prices.append(price_to_bytes) - - return injective_oracle_tx_pb.MsgRelayProviderPrices( - sender=sender, provider=provider, symbols=symbols, prices=oracle_prices + def MsgBatchCancelDerivativeOrders(self, sender: str, data: List): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_cancel_derivative_orders` instead + """ + warn( + "This method is deprecated. Use msg_batch_cancel_derivative_orders instead", + DeprecationWarning, + stacklevel=2, ) + return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders(sender=sender, data=data) + + def msg_batch_cancel_derivative_orders( + self, sender: str, orders_data: List[injective_exchange_tx_pb.OrderData] + ) -> injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders: + return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders(sender=sender, data=orders_data) def MsgInstantBinaryOptionsMarketLaunch( self, @@ -622,6 +1204,15 @@ def MsgInstantBinaryOptionsMarketLaunch( min_quantity_tick_size: float, **kwargs, ): + """ + This method is deprecated and will be removed soon. + Please use `msg_instant_binary_options_market_launch` instead + """ + warn( + "This method is deprecated. Use msg_instant_binary_options_market_launch instead", + DeprecationWarning, + stacklevel=2, + ) scaled_maker_fee_rate = Decimal((maker_fee_rate * pow(10, 18))) maker_fee_to_bytes = bytes(str(scaled_maker_fee_rate), "utf-8") @@ -651,75 +1242,281 @@ def MsgInstantBinaryOptionsMarketLaunch( admin=kwargs.get("admin"), ) - def MsgCancelDerivativeOrder( + def msg_instant_binary_options_market_launch( self, - market_id: str, sender: str, - subaccount_id: str, - order_hash: Optional[str] = None, - cid: Optional[str] = None, - **kwargs, - ): - order_mask = self.get_order_mask(**kwargs) - - return injective_exchange_tx_pb.MsgCancelDerivativeOrder( + ticker: str, + oracle_symbol: str, + oracle_provider: str, + oracle_type: str, + oracle_scale_factor: int, + maker_fee_rate: Decimal, + taker_fee_rate: Decimal, + expiration_timestamp: int, + settlement_timestamp: int, + admin: str, + quote_denom: str, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch: + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_exchange_tx_pb.MsgInstantBinaryOptionsMarketLaunch( sender=sender, - market_id=market_id, - subaccount_id=subaccount_id, - order_hash=order_hash, - order_mask=order_mask, - cid=cid, + ticker=ticker, + oracle_symbol=oracle_symbol, + oracle_provider=oracle_provider, + oracle_type=injective_oracle_pb.OracleType.Value(oracle_type), + oracle_scale_factor=oracle_scale_factor, + maker_fee_rate=f"{chain_maker_fee_rate.normalize():f}", + taker_fee_rate=f"{chain_taker_fee_rate.normalize():f}", + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + admin=admin, + quote_denom=quote_token.denom, + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", ) - def MsgBatchCreateDerivativeLimitOrders(self, sender: str, orders: List): - return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders(sender=sender, orders=orders) + def MsgCreateBinaryOptionsLimitOrder( + self, + market_id: str, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: float, + quantity: float, + cid: Optional[str] = None, + **kwargs, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_create_binary_options_limit_order` instead + """ + warn( + "This method is deprecated. Use msg_create_binary_options_limit_order instead", + DeprecationWarning, + stacklevel=2, + ) + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) - def MsgBatchCancelDerivativeOrders(self, sender: str, data: List): - return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders(sender=sender, data=data) + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) - def MsgBatchUpdateOrders(self, sender: str, **kwargs): - return injective_exchange_tx_pb.MsgBatchUpdateOrders( + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + + return injective_exchange_tx_pb.MsgCreateBinaryOptionsLimitOrder( sender=sender, - subaccount_id=kwargs.get("subaccount_id"), - spot_market_ids_to_cancel_all=kwargs.get("spot_market_ids_to_cancel_all"), - derivative_market_ids_to_cancel_all=kwargs.get("derivative_market_ids_to_cancel_all"), - spot_orders_to_cancel=kwargs.get("spot_orders_to_cancel"), - derivative_orders_to_cancel=kwargs.get("derivative_orders_to_cancel"), - spot_orders_to_create=kwargs.get("spot_orders_to_create"), - derivative_orders_to_create=kwargs.get("derivative_orders_to_create"), - binary_options_orders_to_cancel=kwargs.get("binary_options_orders_to_cancel"), - binary_options_market_ids_to_cancel_all=kwargs.get("binary_options_market_ids_to_cancel_all"), - binary_options_orders_to_create=kwargs.get("binary_options_orders_to_create"), + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, + denom=kwargs.get("denom"), + ), ) - def MsgLiquidatePosition( + def msg_create_binary_options_limit_order( self, + market_id: str, sender: str, subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + denom: Optional[Denom] = None, + ) -> injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder: + return injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder( + sender=sender, + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + denom=denom, + ), + ) + + def MsgCreateBinaryOptionsMarketOrder( + self, market_id: str, - order: Optional[injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.DerivativeOrder] = None, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: float, + quantity: float, + cid: Optional[str] = None, + **kwargs, ): - return injective_exchange_tx_pb.MsgLiquidatePosition( - sender=sender, subaccount_id=subaccount_id, market_id=market_id, order=order + """ + This method is deprecated and will be removed soon. Please use `msg_create_binary_options_market_order` instead + """ + warn( + "This method is deprecated. Use msg_create_binary_options_market_order instead", + DeprecationWarning, + stacklevel=2, ) + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) - def MsgIncreasePositionMargin( + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + + return injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder( + sender=sender, + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, + denom=kwargs.get("denom"), + ), + ) + + def msg_create_binary_options_market_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + denom: Optional[Denom] = None, + ): + return injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder( + sender=sender, + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + denom=denom, + ), + ) + + def MsgCancelBinaryOptionsOrder( self, sender: str, - source_subaccount_id: str, - destination_subaccount_id: str, market_id: str, - amount: float, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, ): - market = self.derivative_markets[market_id] + """ + This method is deprecated and will be removed soon. Please use `msg_cancel_binary_options_order` instead + """ + warn( + "This method is deprecated. Use msg_cancel_binary_options_order instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder( + sender=sender, + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + ) - additional_margin = market.margin_to_chain_format(human_readable_value=Decimal(str(amount))) - return injective_exchange_tx_pb.MsgIncreasePositionMargin( + def msg_cancel_binary_options_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + is_conditional: Optional[bool] = False, + is_buy: Optional[bool] = False, + is_market_order: Optional[bool] = False, + ) -> injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder: + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) + + return injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder( sender=sender, - source_subaccount_id=source_subaccount_id, - destination_subaccount_id=destination_subaccount_id, market_id=market_id, - amount=str(int(additional_margin)), + subaccount_id=subaccount_id, + order_hash=order_hash, + order_mask=order_mask, + cid=cid, ) def MsgSubaccountTransfer( @@ -730,6 +1527,14 @@ def MsgSubaccountTransfer( amount: int, denom: str, ): + """ + This method is deprecated and will be removed soon. Please use `msg_subaccount_transfer` instead + """ + warn( + "This method is deprecated. Use msg_subaccount_transfer instead", + DeprecationWarning, + stacklevel=2, + ) be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgSubaccountTransfer( @@ -739,12 +1544,20 @@ def MsgSubaccountTransfer( amount=be_amount, ) - def MsgWithdraw(self, sender: str, subaccount_id: str, amount: float, denom: str): - be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + def msg_subaccount_transfer( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + amount: Decimal, + denom: str, + ) -> injective_exchange_tx_pb.MsgSubaccountTransfer: + be_amount = self.create_coin_amount(amount=amount, token_name=denom) - return injective_exchange_tx_pb.MsgWithdraw( + return injective_exchange_tx_pb.MsgSubaccountTransfer( sender=sender, - subaccount_id=subaccount_id, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, amount=be_amount, ) @@ -756,6 +1569,14 @@ def MsgExternalTransfer( amount: int, denom: str, ): + """ + This method is deprecated and will be removed soon. Please use `msg_external_transfer` instead + """ + warn( + "This method is deprecated. Use msg_external_transfer instead", + DeprecationWarning, + stacklevel=2, + ) coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgExternalTransfer( @@ -765,129 +1586,184 @@ def MsgExternalTransfer( amount=coin, ) - def MsgBid(self, sender: str, bid_amount: float, round: float): - be_amount = Decimal(str(bid_amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + def msg_external_transfer( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + amount: Decimal, + denom: str, + ) -> injective_exchange_tx_pb.MsgExternalTransfer: + coin = self.create_coin_amount(amount=amount, token_name=denom) - return injective_auction_tx_pb.MsgBid( + return injective_exchange_tx_pb.MsgExternalTransfer( sender=sender, - round=round, - bid_amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=coin, ) - def MsgGrantGeneric(self, granter: str, grantee: str, msg_type: str, expire_in: int): - auth = cosmos_authz_pb.GenericAuthorization(msg=msg_type) - any_auth = any_pb2.Any() - any_auth.Pack(auth, type_url_prefix="") - - grant = cosmos_authz_pb.Grant( - authorization=any_auth, - expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), + def MsgLiquidatePosition( + self, + sender: str, + subaccount_id: str, + market_id: str, + order: Optional[injective_exchange_pb.DerivativeOrder] = None, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_liquidate_position` instead + """ + warn( + "This method is deprecated. Use msg_liquidate_position instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgLiquidatePosition( + sender=sender, subaccount_id=subaccount_id, market_id=market_id, order=order ) - return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + def msg_liquidate_position( + self, + sender: str, + subaccount_id: str, + market_id: str, + order: Optional[injective_exchange_pb.DerivativeOrder] = None, + ) -> injective_exchange_tx_pb.MsgLiquidatePosition: + return injective_exchange_tx_pb.MsgLiquidatePosition( + sender=sender, subaccount_id=subaccount_id, market_id=market_id, order=order + ) - def MsgGrantTyped( + def msg_emergency_settle_market( self, - granter: str, - grantee: str, - msg_type: str, - expire_in: int, + sender: str, subaccount_id: str, - **kwargs, + market_id: str, + ) -> injective_exchange_tx_pb.MsgEmergencySettleMarket: + return injective_exchange_tx_pb.MsgEmergencySettleMarket( + sender=sender, subaccount_id=subaccount_id, market_id=market_id + ) + + def MsgIncreasePositionMargin( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + market_id: str, + amount: float, ): - auth = None - if msg_type == "CreateSpotLimitOrderAuthz": - auth = injective_authz_pb.CreateSpotLimitOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CreateSpotMarketOrderAuthz": - auth = injective_authz_pb.CreateSpotMarketOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCreateSpotLimitOrdersAuthz": - auth = injective_authz_pb.BatchCreateSpotLimitOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CancelSpotOrderAuthz": - auth = injective_authz_pb.CancelSpotOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCancelSpotOrdersAuthz": - auth = injective_authz_pb.BatchCancelSpotOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CreateDerivativeLimitOrderAuthz": - auth = injective_authz_pb.CreateDerivativeLimitOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CreateDerivativeMarketOrderAuthz": - auth = injective_authz_pb.CreateDerivativeMarketOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCreateDerivativeLimitOrdersAuthz": - auth = injective_authz_pb.BatchCreateDerivativeLimitOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CancelDerivativeOrderAuthz": - auth = injective_authz_pb.CancelDerivativeOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCancelDerivativeOrdersAuthz": - auth = injective_authz_pb.BatchCancelDerivativeOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchUpdateOrdersAuthz": - auth = injective_authz_pb.BatchUpdateOrdersAuthz( - subaccount_id=subaccount_id, - spot_markets=kwargs.get("spot_markets"), - derivative_markets=kwargs.get("derivative_markets"), - ) + """ + This method is deprecated and will be removed soon. Please use `msg_increase_position_margin` instead + """ + warn( + "This method is deprecated. Use msg_increase_position_margin instead", + DeprecationWarning, + stacklevel=2, + ) + market = self.derivative_markets[market_id] - any_auth = any_pb2.Any() - any_auth.Pack(auth, type_url_prefix="") + additional_margin = market.margin_to_chain_format(human_readable_value=Decimal(str(amount))) + return injective_exchange_tx_pb.MsgIncreasePositionMargin( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + market_id=market_id, + amount=str(int(additional_margin)), + ) - grant = cosmos_authz_pb.Grant( - authorization=any_auth, - expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), + def msg_increase_position_margin( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + market_id: str, + amount: Decimal, + ): + market = self.derivative_markets[market_id] + + additional_margin = market.margin_to_chain_format(human_readable_value=amount) + return injective_exchange_tx_pb.MsgIncreasePositionMargin( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + market_id=market_id, + amount=str(int(additional_margin)), ) - return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) - - def MsgExec(self, grantee: str, msgs: List): - any_msgs: List[any_pb2.Any] = [] - for msg in msgs: - any_msg = any_pb2.Any() - any_msg.Pack(msg, type_url_prefix="") - any_msgs.append(any_msg) + def MsgRewardsOptOut(self, sender: str): + """ + This method is deprecated and will be removed soon. Please use `msg_rewards_opt_out` instead + """ + warn( + "This method is deprecated. Use msg_rewards_opt_out instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgRewardsOptOut(sender=sender) - return cosmos_authz_tx_pb.MsgExec(grantee=grantee, msgs=any_msgs) + def msg_rewards_opt_out(self, sender: str) -> injective_exchange_tx_pb.MsgRewardsOptOut: + return injective_exchange_tx_pb.MsgRewardsOptOut(sender=sender) - def MsgRevoke(self, granter: str, grantee: str, msg_type: str): - return cosmos_authz_tx_pb.MsgRevoke(granter=granter, grantee=grantee, msg_type_url=msg_type) + def MsgAdminUpdateBinaryOptionsMarket( + self, + sender: str, + market_id: str, + status: str, + **kwargs, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_admin_update_binary_options_market` instead + """ + warn( + "This method is deprecated. Use msg_admin_update_binary_options_market instead", + DeprecationWarning, + stacklevel=2, + ) - def MsgRelayPriceFeedPrice(self, sender: list, base: list, quote: list, price: list): - return injective_oracle_tx_pb.MsgRelayPriceFeedPrice(sender=sender, base=base, quote=quote, price=price) + if kwargs.get("settlement_price") is not None: + scale_price = Decimal((kwargs.get("settlement_price") * pow(10, 18))) + price_to_bytes = bytes(str(scale_price), "utf-8") - def MsgSendToEth(self, denom: str, sender: str, eth_dest: str, amount: float, bridge_fee: float): - be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) - be_bridge_fee = self.create_coin_amount(amount=Decimal(str(bridge_fee)), token_name=denom) + else: + price_to_bytes = "" - return injective_peggy_tx_pb.MsgSendToEth( + return injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket( sender=sender, - eth_dest=eth_dest, - amount=be_amount, - bridge_fee=be_bridge_fee, + market_id=market_id, + settlement_price=price_to_bytes, + expiration_timestamp=kwargs.get("expiration_timestamp"), + settlement_timestamp=kwargs.get("settlement_timestamp"), + status=status, ) - def MsgDelegate(self, delegator_address: str, validator_address: str, amount: float): - be_amount = Decimal(str(amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + def msg_admin_update_binary_options_market( + self, + sender: str, + market_id: str, + status: str, + settlement_price: Optional[Decimal] = None, + expiration_timestamp: Optional[int] = None, + settlement_timestamp: Optional[int] = None, + ) -> injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket: + market = self.binary_option_markets[market_id] - return cosmos_staking_tx_pb.MsgDelegate( - delegator_address=delegator_address, - validator_address=validator_address, - amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), + if settlement_price is not None: + chain_settlement_price = market.price_to_chain_format(human_readable_value=settlement_price) + price_parameter = f"{chain_settlement_price.normalize():f}" + else: + price_parameter = None + + return injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket( + sender=sender, + market_id=market_id, + settlement_price=price_parameter, + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + status=status, ) + # endregion + + # region Insurance module def MsgCreateInsuranceFund( self, sender: str, @@ -941,38 +1817,53 @@ def MsgRequestRedemption( amount=self.coin(amount=amount, denom=share_denom), ) - def MsgVote( - self, - proposal_id: str, - voter: str, - option: int, - ): - return cosmos_gov_tx_pb.MsgVote(proposal_id=proposal_id, voter=voter, option=option) + # endregion - def MsgPrivilegedExecuteContract( - self, sender: str, contract: str, msg: str, **kwargs - ) -> injective_exchange_tx_pb.MsgPrivilegedExecuteContract: - return injective_exchange_tx_pb.MsgPrivilegedExecuteContract( - sender=sender, - contract_address=contract, - data=msg, - funds=kwargs.get("funds") # funds is a string of Coin strings, comma separated, - # e.g. 100000inj,20000000000usdt + # region Oracle module + def MsgRelayProviderPrices(self, sender: str, provider: str, symbols: list, prices: list): + oracle_prices = [] + + for price in prices: + scale_price = Decimal((price) * pow(10, 18)) + price_to_bytes = bytes(str(scale_price), "utf-8") + oracle_prices.append(price_to_bytes) + + return injective_oracle_tx_pb.MsgRelayProviderPrices( + sender=sender, provider=provider, symbols=symbols, prices=oracle_prices ) - def MsgInstantiateContract( - self, sender: str, admin: str, code_id: int, label: str, message: bytes, **kwargs - ) -> wasm_tx_pb.MsgInstantiateContract: - return wasm_tx_pb.MsgInstantiateContract( + def MsgRelayPriceFeedPrice(self, sender: list, base: list, quote: list, price: list): + return injective_oracle_tx_pb.MsgRelayPriceFeedPrice(sender=sender, base=base, quote=quote, price=price) + + # endregion + + # region Peggy module + def MsgSendToEth(self, denom: str, sender: str, eth_dest: str, amount: float, bridge_fee: float): + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + be_bridge_fee = self.create_coin_amount(amount=Decimal(str(bridge_fee)), token_name=denom) + + return injective_peggy_tx_pb.MsgSendToEth( sender=sender, - admin=admin, - code_id=code_id, - label=label, - msg=message, - funds=kwargs.get("funds"), # funds is a list of cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin. - # The coins in the list must be sorted in alphabetical order by denoms. + eth_dest=eth_dest, + amount=be_amount, + bridge_fee=be_bridge_fee, + ) + + # endregion + + # region Staking module + def MsgDelegate(self, delegator_address: str, validator_address: str, amount: float): + be_amount = Decimal(str(amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return cosmos_staking_tx_pb.MsgDelegate( + delegator_address=delegator_address, + validator_address=validator_address, + amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), ) + # endregion + + # region Tokenfactory module def msg_create_denom( self, sender: str, @@ -990,14 +1881,14 @@ def msg_create_denom( def msg_mint( self, sender: str, - amount: cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin, + amount: base_coin_pb.Coin, ) -> token_factory_tx_pb.MsgMint: return token_factory_tx_pb.MsgMint(sender=sender, amount=amount) def msg_burn( self, sender: str, - amount: cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin, + amount: base_coin_pb.Coin, ) -> token_factory_tx_pb.MsgBurn: return token_factory_tx_pb.MsgBurn(sender=sender, amount=amount) @@ -1047,14 +1938,108 @@ def msg_change_admin( new_admin=new_admin, ) - def msg_execute_contract_compat(self, sender: str, contract: str, msg: str, funds: str): - return wasmx_tx_pb.MsgExecuteContractCompat( + # endregion + + # region Wasm module + def MsgInstantiateContract( + self, sender: str, admin: str, code_id: int, label: str, message: bytes, **kwargs + ) -> wasm_tx_pb.MsgInstantiateContract: + return wasm_tx_pb.MsgInstantiateContract( + sender=sender, + admin=admin, + code_id=code_id, + label=label, + msg=message, + funds=kwargs.get("funds"), # funds is a list of base_coin_pb.Coin. + # The coins in the list must be sorted in alphabetical order by denoms. + ) + + def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): + return wasm_tx_pb.MsgExecuteContract( sender=sender, contract=contract, - msg=msg, - funds=funds, + msg=bytes(msg, "utf-8"), + funds=kwargs.get("funds") # funds is a list of base_coin_pb.Coin. + # The coins in the list must be sorted in alphabetical order by denoms. + ) + + # endregion + + def MsgGrantTyped( + self, + granter: str, + grantee: str, + msg_type: str, + expire_in: int, + subaccount_id: str, + **kwargs, + ): + auth = None + if msg_type == "CreateSpotLimitOrderAuthz": + auth = injective_authz_pb.CreateSpotLimitOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CreateSpotMarketOrderAuthz": + auth = injective_authz_pb.CreateSpotMarketOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCreateSpotLimitOrdersAuthz": + auth = injective_authz_pb.BatchCreateSpotLimitOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CancelSpotOrderAuthz": + auth = injective_authz_pb.CancelSpotOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCancelSpotOrdersAuthz": + auth = injective_authz_pb.BatchCancelSpotOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CreateDerivativeLimitOrderAuthz": + auth = injective_authz_pb.CreateDerivativeLimitOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CreateDerivativeMarketOrderAuthz": + auth = injective_authz_pb.CreateDerivativeMarketOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCreateDerivativeLimitOrdersAuthz": + auth = injective_authz_pb.BatchCreateDerivativeLimitOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CancelDerivativeOrderAuthz": + auth = injective_authz_pb.CancelDerivativeOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCancelDerivativeOrdersAuthz": + auth = injective_authz_pb.BatchCancelDerivativeOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchUpdateOrdersAuthz": + auth = injective_authz_pb.BatchUpdateOrdersAuthz( + subaccount_id=subaccount_id, + spot_markets=kwargs.get("spot_markets"), + derivative_markets=kwargs.get("derivative_markets"), + ) + + any_auth = any_pb2.Any() + any_auth.Pack(auth, type_url_prefix="") + + grant = cosmos_authz_pb.Grant( + authorization=any_auth, + expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), ) + return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + + def MsgVote( + self, + proposal_id: str, + voter: str, + option: int, + ): + return cosmos_gov_tx_pb.MsgVote(proposal_id=proposal_id, voter=voter, option=option) + def chain_stream_bank_balances_filter( self, accounts: Optional[List[str]] = None ) -> chain_stream_query.BankBalancesFilter: @@ -1144,7 +2129,7 @@ def MsgWithdrawValidatorCommission(self, validator_address: str): def msg_withdraw_validator_commission(self, validator_address: str): return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) - def msg_fund_community_pool(self, amounts: List[cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin], depositor: str): + def msg_fund_community_pool(self, amounts: List[base_coin_pb.Coin], depositor: str): return cosmos_distribution_tx_pb.MsgFundCommunityPool(amount=amounts, depositor=depositor) def msg_update_distribution_params(self, authority: str, community_tax: str, withdraw_address_enabled: bool): @@ -1154,9 +2139,7 @@ def msg_update_distribution_params(self, authority: str, community_tax: str, wit ) return cosmos_distribution_tx_pb.MsgUpdateParams(authority=authority, params=params) - def msg_community_pool_spend( - self, authority: str, recipient: str, amount: List[cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin] - ): + def msg_community_pool_spend(self, authority: str, recipient: str, amount: List[base_coin_pb.Coin]): return cosmos_distribution_tx_pb.MsgCommunityPoolSpend(authority=authority, recipient=recipient, amount=amount) # data field format: [request-msg-header][raw-byte-msg-response] @@ -1369,3 +2352,61 @@ def _initialize_markets_and_tokens_from_files(self): self.spot_markets = spot_markets self.derivative_markets = derivative_markets self.binary_option_markets = dict() + + def _order_mask(self, is_conditional: bool, is_buy: bool, is_market_order: bool) -> int: + order_mask = 0 + + if is_conditional: + order_mask += injective_exchange_pb.OrderMask.CONDITIONAL + else: + order_mask += injective_exchange_pb.OrderMask.REGULAR + + if is_buy: + order_mask += injective_exchange_pb.OrderMask.DIRECTION_BUY_OR_HIGHER + else: + order_mask += injective_exchange_pb.OrderMask.DIRECTION_SELL_OR_LOWER + + if is_market_order: + order_mask += injective_exchange_pb.OrderMask.TYPE_MARKET + else: + order_mask += injective_exchange_pb.OrderMask.TYPE_LIMIT + + if order_mask == 0: + order_mask = 1 + + return order_mask + + def _basic_derivative_order( + self, + market_id: str, + subaccount_id: str, + fee_recipient: str, + chain_price: Decimal, + chain_quantity: Decimal, + chain_margin: Decimal, + order_type: str, + cid: Optional[str] = None, + chain_trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_pb.DerivativeOrder: + formatted_quantity = f"{chain_quantity.normalize():f}" + formatted_price = f"{chain_price.normalize():f}" + formatted_margin = f"{chain_margin.normalize():f}" + + trigger_price = chain_trigger_price or Decimal(0) + formatted_trigger_price = f"{trigger_price.normalize():f}" + + chain_order_type = injective_exchange_pb.OrderType.Value(order_type) + + return injective_exchange_pb.DerivativeOrder( + market_id=market_id, + order_info=injective_exchange_pb.OrderInfo( + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=formatted_price, + quantity=formatted_quantity, + cid=cid, + ), + order_type=chain_order_type, + margin=formatted_margin, + trigger_price=formatted_trigger_price, + ) diff --git a/pyinjective/core/market.py b/pyinjective/core/market.py index 2bd4fe1b..66063130 100644 --- a/pyinjective/core/market.py +++ b/pyinjective/core/market.py @@ -169,6 +169,17 @@ def price_to_chain_format(self, human_readable_value: Decimal, special_denom: Op return extended_chain_formatted_value + def margin_to_chain_format(self, human_readable_value: Decimal, special_denom: Optional[Denom] = None) -> Decimal: + decimals = self.quote_token.decimals if special_denom is None else special_denom.quote + min_quantity_tick_size = ( + self.min_quantity_tick_size if special_denom is None else special_denom.min_quantity_tick_size + ) + chain_formatted_value = human_readable_value * Decimal(f"1e{decimals}") + quantized_value = (chain_formatted_value // min_quantity_tick_size) * min_quantity_tick_size + extended_chain_formatted_value = quantized_value * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return extended_chain_formatted_value + def calculate_margin_in_chain_format( self, human_readable_quantity: Decimal, diff --git a/tests/core/test_gas_limit_estimator.py b/tests/core/test_gas_limit_estimator.py index 916c47a9..293f5f25 100644 --- a/tests/core/test_gas_limit_estimator.py +++ b/tests/core/test_gas_limit_estimator.py @@ -24,26 +24,24 @@ def test_estimation_for_batch_create_spot_limit_orders(self): spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=5, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("5"), + quantity=Decimal("1"), + order_type="BUY", ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=4, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("4"), + quantity=Decimal("1"), + order_type="BUY", ), ] - message = composer.MsgBatchCreateSpotLimitOrders(sender="sender", orders=orders) + message = composer.msg_batch_create_spot_limit_orders(sender="sender", orders=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 50000 @@ -55,23 +53,23 @@ def test_estimation_for_batch_cancel_spot_orders(self): spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", ), ] - message = composer.MsgBatchCancelSpotOrders(sender="sender", data=orders) + message = composer.msg_batch_cancel_spot_orders(sender="sender", orders_data=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 50000 @@ -83,28 +81,26 @@ def test_estimation_for_batch_create_derivative_limit_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=3, - quantity=1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(3), + quantity=Decimal(1), + margin=Decimal(3), + order_type="BUY", ), - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=20, - quantity=1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(20), + quantity=Decimal(1), + margin=Decimal(20), + order_type="SELL", ), ] - message = composer.MsgBatchCreateDerivativeLimitOrders(sender="sender", orders=orders) + message = composer.msg_batch_create_derivative_limit_orders(sender="sender", orders=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 70_000 @@ -116,23 +112,23 @@ def test_estimation_for_batch_cancel_derivative_orders(self): spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", ), ] - message = composer.MsgBatchCancelDerivativeOrders(sender="sender", data=orders) + message = composer.msg_batch_cancel_derivative_orders(sender="sender", orders_data=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 60_000 @@ -144,23 +140,21 @@ def test_estimation_for_batch_update_orders_to_create_spot_orders(self): market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.SpotOrder( + composer.spot_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=5, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("5"), + quantity=Decimal("1"), + order_type="BUY", ), - composer.SpotOrder( + composer.spot_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=4, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("4"), + quantity=Decimal("1"), + order_type="BUY", ), ] message = composer.MsgBatchUpdateOrders( @@ -181,25 +175,23 @@ def test_estimation_for_batch_update_orders_to_create_derivative_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=3, - quantity=1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(3), + quantity=Decimal(1), + margin=Decimal(3), + order_type="BUY", ), - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=20, - quantity=1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(20), + quantity=Decimal(1), + margin=Decimal(20), + order_type="SELL", ), ] message = composer.MsgBatchUpdateOrders( @@ -238,25 +230,23 @@ def test_estimation_for_batch_update_orders_to_create_binary_orders(self, usdt_t ) composer.binary_option_markets[market.id] = market orders = [ - composer.BinaryOptionsOrder( + composer.binary_options_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=3, - quantity=1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(3), + quantity=Decimal(1), + margin=Decimal(3), + order_type="BUY", ), - composer.BinaryOptionsOrder( + composer.binary_options_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=20, - quantity=1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(20), + quantity=Decimal(1), + margin=Decimal(20), + order_type="SELL", ), ] message = composer.MsgBatchUpdateOrders( @@ -278,17 +268,17 @@ def test_estimation_for_batch_update_orders_to_cancel_spot_orders(self): market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -312,17 +302,17 @@ def test_estimation_for_batch_update_orders_to_cancel_derivative_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -346,17 +336,17 @@ def test_estimation_for_batch_update_orders_to_cancel_binary_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -441,14 +431,13 @@ def test_estimation_for_exec_message(self): market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.SpotOrder( + composer.spot_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=5, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("5"), + quantity=Decimal("1"), + order_type="BUY", ), ] inner_message = composer.MsgBatchUpdateOrders( @@ -510,15 +499,14 @@ def test_estimation_for_governance_message(self): def test_estimation_for_generic_exchange_message(self): composer = Composer(network="testnet") - message = composer.MsgCreateSpotLimitOrder( + message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) estimator = GasLimitEstimator.for_message(message=message) diff --git a/tests/core/test_market.py b/tests/core/test_market.py index ede8aea5..48c2f5e5 100644 --- a/tests/core/test_market.py +++ b/tests/core/test_market.py @@ -248,6 +248,42 @@ def test_convert_price_to_chain_format_without_fixed_denom(self, first_match_bet assert quantized_chain_format_value == chain_value + def test_convert_margin_to_chain_format_with_fixed_denom(self, first_match_bet_market: BinaryOptionMarket): + original_quantity = Decimal("123.456789") + fixed_denom = Denom( + description="Fixed denom", + base=2, + quote=4, + min_quantity_tick_size=100, + min_price_tick_size=10000, + ) + + chain_value = first_match_bet_market.margin_to_chain_format( + human_readable_value=original_quantity, + special_denom=fixed_denom, + ) + price_decimals = fixed_denom.quote + expected_value = original_quantity * Decimal(f"1e{price_decimals}") + quantized_value = (expected_value // Decimal(str(fixed_denom.min_quantity_tick_size))) * Decimal( + str(fixed_denom.min_quantity_tick_size) + ) + quantized_chain_format_value = quantized_value * Decimal("1e18") + + assert quantized_chain_format_value == chain_value + + def test_convert_margin_to_chain_format_without_fixed_denom(self, first_match_bet_market: BinaryOptionMarket): + original_quantity = Decimal("123.456789") + + chain_value = first_match_bet_market.margin_to_chain_format(human_readable_value=original_quantity) + price_decimals = first_match_bet_market.quote_token.decimals + expected_value = original_quantity * Decimal(f"1e{price_decimals}") + quantized_value = ( + expected_value // first_match_bet_market.min_quantity_tick_size + ) * first_match_bet_market.min_quantity_tick_size + quantized_chain_format_value = quantized_value * Decimal("1e18") + + assert quantized_chain_format_value == chain_value + def test_calculate_margin_for_buy_with_fixed_denom(self, first_match_bet_market: BinaryOptionMarket): original_quantity = Decimal("123.456789") original_price = Decimal("0.6789") diff --git a/tests/core/test_message_based_transaction_fee_calculator.py b/tests/core/test_message_based_transaction_fee_calculator.py index 23e263c9..b1d774e0 100644 --- a/tests/core/test_message_based_transaction_fee_calculator.py +++ b/tests/core/test_message_based_transaction_fee_calculator.py @@ -117,15 +117,14 @@ async def test_gas_fee_for_exchange_message(self): gas_price=5_000_000, ) - message = composer.MsgCreateSpotLimitOrder( + message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) transaction = Transaction() transaction.with_messages(message) @@ -148,15 +147,14 @@ async def test_gas_fee_for_msg_exec_message(self): gas_price=5_000_000, ) - inner_message = composer.MsgCreateSpotLimitOrder( + inner_message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) message = composer.MsgExec(grantee="grantee", msgs=[inner_message]) transaction = Transaction() @@ -184,15 +182,14 @@ async def test_gas_fee_for_two_messages_in_one_transaction(self): gas_price=5_000_000, ) - inner_message = composer.MsgCreateSpotLimitOrder( + inner_message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) message = composer.MsgExec(grantee="grantee", msgs=[inner_message]) diff --git a/tests/test_composer.py b/tests/test_composer.py index a0cca2ab..2dcbd056 100644 --- a/tests/test_composer.py +++ b/tests/test_composer.py @@ -2,12 +2,11 @@ from decimal import Decimal import pytest +from google.protobuf import json_format from pyinjective.composer import Composer -from pyinjective.core.market import BinaryOptionMarket, DerivativeMarket, SpotMarket +from pyinjective.constant import ADDITIONAL_CHAIN_FORMAT_DECIMALS from pyinjective.core.network import Network -from pyinjective.proto.injective.exchange.v1beta1 import exchange_pb2 -from pyinjective.utils.denom import Denom from tests.model_fixtures.markets_fixtures import btc_usdt_perp_market # noqa: F401 from tests.model_fixtures.markets_fixtures import first_match_bet_market # noqa: F401 from tests.model_fixtures.markets_fixtures import inj_token # noqa: F401 @@ -57,211 +56,6 @@ def test_composer_initialization_from_ini_files(self): assert 6 == inj_usdt_spot_market.quote_token.decimals assert 6 == inj_usdt_perp_market.quote_token.decimals - def test_buy_spot_order_creation(self, basic_composer: Composer, inj_usdt_spot_market: SpotMarket): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - order = basic_composer.SpotOrder( - market_id=inj_usdt_spot_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - ) - - price_decimals = inj_usdt_spot_market.quote_token.decimals - inj_usdt_spot_market.base_token.decimals - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // inj_usdt_spot_market.min_price_tick_size) - * inj_usdt_spot_market.min_price_tick_size - * Decimal("1e18") - ) - chain_format_quantity = Decimal(str(quantity)) * Decimal(f"1e{inj_usdt_spot_market.base_token.decimals}") - expected_quantity = ( - (chain_format_quantity // inj_usdt_spot_market.min_quantity_tick_size) - * inj_usdt_spot_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert order.market_id == inj_usdt_spot_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.trigger_price == "0" - - def test_buy_derivative_order_creation(self, basic_composer: Composer, btc_usdt_perp_market: DerivativeMarket): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - leverage = 2 - order = basic_composer.DerivativeOrder( - market_id=btc_usdt_perp_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - leverage=leverage, - ) - - price_decimals = btc_usdt_perp_market.quote_token.decimals - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // btc_usdt_perp_market.min_price_tick_size) - * btc_usdt_perp_market.min_price_tick_size - * Decimal("1e18") - ) - chain_format_quantity = Decimal(str(quantity)) - expected_quantity = ( - (chain_format_quantity // btc_usdt_perp_market.min_quantity_tick_size) - * btc_usdt_perp_market.min_quantity_tick_size - * Decimal("1e18") - ) - chain_format_margin = (chain_format_quantity * chain_format_price) / Decimal(leverage) - expected_margin = ( - (chain_format_margin // btc_usdt_perp_market.min_quantity_tick_size) - * btc_usdt_perp_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert order.market_id == btc_usdt_perp_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.margin == str(int(expected_margin)) - assert order.trigger_price == "0" - - def test_increase_position_margin(self, basic_composer: Composer, btc_usdt_perp_market: DerivativeMarket): - sender = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - amount = 1587.789 - message = basic_composer.MsgIncreasePositionMargin( - sender=sender, - source_subaccount_id="1", - destination_subaccount_id="2", - market_id=btc_usdt_perp_market.id, - amount=amount, - ) - - price_decimals = btc_usdt_perp_market.quote_token.decimals - chain_format_margin = Decimal(str(amount)) * Decimal(f"1e{price_decimals}") - expected_margin = ( - (chain_format_margin // btc_usdt_perp_market.min_quantity_tick_size) - * btc_usdt_perp_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert message.market_id == btc_usdt_perp_market.id - assert message.sender == sender - assert message.source_subaccount_id == "1" - assert message.destination_subaccount_id == "2" - assert message.amount == str(int(expected_margin)) - - def test_buy_binary_option_order_creation_with_fixed_denom( - self, basic_composer: Composer, first_match_bet_market: BinaryOptionMarket - ): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - fixed_denom = Denom( - description="Fixed denom", - base=2, - quote=6, - min_price_tick_size=1000, - min_quantity_tick_size=10000, - ) - - order = basic_composer.BinaryOptionsOrder( - market_id=first_match_bet_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - denom=fixed_denom, - ) - - price_decimals = fixed_denom.quote - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // Decimal(str(fixed_denom.min_price_tick_size))) - * Decimal(str(fixed_denom.min_price_tick_size)) - * Decimal("1e18") - ) - quantity_decimals = fixed_denom.base - chain_format_quantity = Decimal(str(quantity)) * Decimal(f"1e{quantity_decimals}") - expected_quantity = ( - (chain_format_quantity // Decimal(str(fixed_denom.min_quantity_tick_size))) - * Decimal(str(fixed_denom.min_quantity_tick_size)) - * Decimal("1e18") - ) - chain_format_margin = chain_format_quantity * chain_format_price - expected_margin = ( - (chain_format_margin // Decimal(str(fixed_denom.min_quantity_tick_size))) - * Decimal(str(fixed_denom.min_quantity_tick_size)) - * Decimal("1e18") - ) - - assert order.market_id == first_match_bet_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.margin == str(int(expected_margin)) - assert order.trigger_price == "0" - - def test_buy_binary_option_order_creation_without_fixed_denom( - self, - basic_composer: Composer, - first_match_bet_market: BinaryOptionMarket, - ): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - - order = basic_composer.BinaryOptionsOrder( - market_id=first_match_bet_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - ) - - price_decimals = first_match_bet_market.quote_token.decimals - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // first_match_bet_market.min_price_tick_size) - * first_match_bet_market.min_price_tick_size - * Decimal("1e18") - ) - chain_format_quantity = Decimal(str(quantity)) - expected_quantity = ( - (chain_format_quantity // first_match_bet_market.min_quantity_tick_size) - * first_match_bet_market.min_quantity_tick_size - * Decimal("1e18") - ) - chain_format_margin = chain_format_quantity * chain_format_price - expected_margin = ( - (chain_format_margin // first_match_bet_market.min_quantity_tick_size) - * first_match_bet_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert order.market_id == first_match_bet_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.margin == str(int(expected_margin)) - assert order.trigger_price == "0" - def test_msg_create_denom(self, basic_composer: Composer): sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" subdenom = "inj-test" @@ -380,3 +174,1259 @@ def test_msg_execute_contract_compat(self, basic_composer): assert message.contract == contract assert message.msg == msg assert message.funds == funds + + def test_msg_deposit(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=Decimal(amount)) + + message = basic_composer.msg_deposit( + sender=sender, + subaccount_id=subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_withdraw(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=Decimal(amount)) + + message = basic_composer.msg_withdraw( + sender=sender, + subaccount_id=subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_spot_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "INJ/USDT" + base_denom = "INJ" + quote_denom = "USDT" + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + + base_token = basic_composer.tokens[base_denom] + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals - base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal( + f"1e{base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + + message = basic_composer.msg_instant_spot_market_launch( + sender=sender, + ticker=ticker, + base_denom=base_denom, + quote_denom=quote_denom, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "baseDenom": base_token.denom, + "quoteDenom": quote_token.denom, + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_perpetual_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "BTC/INJ PERP" + quote_denom = "INJ" + oracle_base = "BTC" + oracle_quote = "INJ" + oracle_scale_factor = 6 + oracle_type = "Band" + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + maker_fee_rate = Decimal("0.001") + taker_fee_rate = Decimal("-0.002") + initial_margin_ratio = Decimal("0.05") + maintenance_margin_ratio = Decimal("0.03") + + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + message = basic_composer.msg_instant_perpetual_market_launch( + sender=sender, + ticker=ticker, + quote_denom=quote_denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=oracle_type, + maker_fee_rate=maker_fee_rate, + taker_fee_rate=taker_fee_rate, + initial_margin_ratio=initial_margin_ratio, + maintenance_margin_ratio=maintenance_margin_ratio, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "quoteDenom": quote_token.denom, + "oracleBase": oracle_base, + "oracleQuote": oracle_quote, + "oracleScaleFactor": oracle_scale_factor, + "oracleType": oracle_type, + "makerFeeRate": f"{expected_maker_fee_rate.normalize():f}", + "takerFeeRate": f"{expected_taker_fee_rate.normalize():f}", + "initialMarginRatio": f"{expected_initial_margin_ratio.normalize():f}", + "maintenanceMarginRatio": f"{expected_maintenance_margin_ratio.normalize():f}", + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_expiry_futures_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "BTC/INJ PERP" + quote_denom = "INJ" + oracle_base = "BTC" + oracle_quote = "INJ" + oracle_scale_factor = 6 + oracle_type = "Band" + expiry = 1630000000 + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + maker_fee_rate = Decimal("0.001") + taker_fee_rate = Decimal("-0.002") + initial_margin_ratio = Decimal("0.05") + maintenance_margin_ratio = Decimal("0.03") + + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + message = basic_composer.msg_instant_expiry_futures_market_launch( + sender=sender, + ticker=ticker, + quote_denom=quote_denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=oracle_type, + expiry=expiry, + maker_fee_rate=maker_fee_rate, + taker_fee_rate=taker_fee_rate, + initial_margin_ratio=initial_margin_ratio, + maintenance_margin_ratio=maintenance_margin_ratio, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "quoteDenom": quote_token.denom, + "oracleBase": oracle_base, + "oracleQuote": oracle_quote, + "oracleType": oracle_type, + "oracleScaleFactor": oracle_scale_factor, + "expiry": str(expiry), + "makerFeeRate": f"{expected_maker_fee_rate.normalize():f}", + "takerFeeRate": f"{expected_taker_fee_rate.normalize():f}", + "initialMarginRatio": f"{expected_initial_margin_ratio.normalize():f}", + "maintenanceMarginRatio": f"{expected_maintenance_margin_ratio.normalize():f}", + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_spot_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.spot_order( + market_id=spot_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = spot_market.price_to_chain_format(human_readable_value=price) + expected_quantity = spot_market.quantity_to_chain_format(human_readable_value=quantity) + expected_trigger_price = spot_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_order = { + "marketId": spot_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=order, + including_default_value_fields=True, + ) + assert dict_message == expected_order + + def test_derivative_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.derivative_order( + market_id=derivative_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = derivative_market.price_to_chain_format(human_readable_value=price) + expected_quantity = derivative_market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = derivative_market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = derivative_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_order = { + "marketId": derivative_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "margin": f"{expected_margin.normalize():f}", + "triggerPrice": f"{expected_trigger_price.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=order, + including_default_value_fields=True, + ) + assert dict_message == expected_order + + def test_msg_create_spot_limit_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_spot_limit_order( + market_id=spot_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = spot_market.price_to_chain_format(human_readable_value=price) + expected_quantity = spot_market.quantity_to_chain_format(human_readable_value=quantity) + expected_trigger_price = spot_market.price_to_chain_format(human_readable_value=trigger_price) + + assert "injective.exchange.v1beta1.MsgCreateSpotLimitOrder" == message.DESCRIPTOR.full_name + expected_message = { + "sender": sender, + "order": { + "marketId": spot_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_create_spot_limit_orders(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.spot_order( + market_id=spot_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + message = basic_composer.msg_batch_create_spot_limit_orders( + sender=sender, + orders=[order], + ) + + expected_message = { + "sender": sender, + "orders": [json_format.MessageToDict(message=order, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_spot_market_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_spot_market_order( + market_id=spot_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = spot_market.price_to_chain_format(human_readable_value=price) + expected_quantity = spot_market.quantity_to_chain_format(human_readable_value=quantity) + expected_trigger_price = spot_market.price_to_chain_format(human_readable_value=trigger_price) + + assert "injective.exchange.v1beta1.MsgCreateSpotMarketOrder" == message.DESCRIPTOR.full_name + expected_message = { + "sender": sender, + "order": { + "marketId": spot_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_cancel_spot_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + order_hash = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + cid = "test_cid" + + message = basic_composer.msg_cancel_spot_order( + market_id=spot_market.id, + sender=sender, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + ) + + expected_message = { + "sender": sender, + "marketId": spot_market.id, + "subaccountId": subaccount_id, + "orderHash": order_hash, + "cid": cid, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_cancel_spot_orders(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + + order_data = basic_composer.order_data( + market_id=spot_market.id, + subaccount_id=subaccount_id, + order_hash="0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000", + ) + + message = basic_composer.msg_batch_cancel_spot_orders( + sender=sender, + orders_data=[order_data], + ) + + assert "injective.exchange.v1beta1.MsgBatchCancelSpotOrders" == message.DESCRIPTOR.full_name + expected_message = { + "sender": sender, + "data": [json_format.MessageToDict(message=order_data, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_update_orders(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + derivative_market = list(basic_composer.derivative_markets.values())[0] + binary_options_market = list(basic_composer.binary_option_markets.values())[0] + + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + spot_market_id = spot_market.id + derivative_market_id = derivative_market.id + binary_options_market_id = binary_options_market.id + spot_order_to_cancel = basic_composer.order_data( + market_id=spot_market_id, + subaccount_id=subaccount_id, + order_hash="0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000", + ) + derivative_order_to_cancel = basic_composer.order_data( + market_id=derivative_market_id, + subaccount_id=subaccount_id, + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", + ) + binary_options_order_to_cancel = basic_composer.order_data( + market_id=binary_options_market_id, + subaccount_id=subaccount_id, + order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", + ) + spot_order_to_create = basic_composer.spot_order( + market_id=spot_market_id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + order_type="BUY", + cid="test_cid", + trigger_price=Decimal("43.5"), + ) + derivative_order_to_create = basic_composer.derivative_order( + market_id=derivative_market_id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + margin=Decimal("36.1") * Decimal("100"), + order_type="BUY", + ) + binary_options_order_to_create = basic_composer.binary_options_order( + market_id=binary_options_market_id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + margin=Decimal("36.1") * Decimal("100"), + order_type="BUY", + ) + + message = basic_composer.msg_batch_update_orders( + sender=sender, + subaccount_id=subaccount_id, + spot_market_ids_to_cancel_all=[spot_market_id], + derivative_market_ids_to_cancel_all=[derivative_market_id], + spot_orders_to_cancel=[spot_order_to_cancel], + derivative_orders_to_cancel=[derivative_order_to_cancel], + spot_orders_to_create=[spot_order_to_create], + derivative_orders_to_create=[derivative_order_to_create], + binary_options_orders_to_cancel=[binary_options_order_to_cancel], + binary_options_market_ids_to_cancel_all=[binary_options_market_id], + binary_options_orders_to_create=[binary_options_order_to_create], + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "spotMarketIdsToCancelAll": [spot_market_id], + "derivativeMarketIdsToCancelAll": [derivative_market_id], + "spotOrdersToCancel": [ + json_format.MessageToDict(message=spot_order_to_cancel, including_default_value_fields=True) + ], + "derivativeOrdersToCancel": [ + json_format.MessageToDict(message=derivative_order_to_cancel, including_default_value_fields=True) + ], + "spotOrdersToCreate": [ + json_format.MessageToDict(message=spot_order_to_create, including_default_value_fields=True) + ], + "derivativeOrdersToCreate": [ + json_format.MessageToDict(message=derivative_order_to_create, including_default_value_fields=True) + ], + "binaryOptionsOrdersToCancel": [ + json_format.MessageToDict(message=binary_options_order_to_cancel, including_default_value_fields=True) + ], + "binaryOptionsMarketIdsToCancelAll": [binary_options_market_id], + "binaryOptionsOrdersToCreate": [ + json_format.MessageToDict(message=binary_options_order_to_create, including_default_value_fields=True) + ], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_privileged_execute_contract(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + contract_address = "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7" + data = "test_data" + funds = "100inj,420peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7" + + message = basic_composer.msg_privileged_execute_contract( + sender=sender, + contract_address=contract_address, + data=data, + funds=funds, + ) + + expected_message = { + "sender": sender, + "funds": funds, + "contractAddress": contract_address, + "data": data, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_derivative_limit_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_derivative_limit_order( + market_id=derivative_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = derivative_market.price_to_chain_format(human_readable_value=price) + expected_quantity = derivative_market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = derivative_market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = derivative_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": derivative_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_create_derivative_limit_orders(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.derivative_order( + market_id=derivative_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=price * quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + message = basic_composer.msg_batch_create_derivative_limit_orders( + sender=sender, + orders=[order], + ) + + expected_message = { + "sender": sender, + "orders": [json_format.MessageToDict(message=order, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_derivative_market_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_derivative_market_order( + market_id=derivative_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = derivative_market.price_to_chain_format(human_readable_value=price) + expected_quantity = derivative_market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = derivative_market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = derivative_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": derivative_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_cancel_derivative_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + order_hash = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + cid = "test_cid" + is_conditional = False + is_buy = True + is_market_order = False + + expected_order_mask = basic_composer._order_mask( + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + message = basic_composer.msg_cancel_derivative_order( + market_id=derivative_market.id, + sender=sender, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + expected_message = { + "sender": sender, + "marketId": derivative_market.id, + "subaccountId": subaccount_id, + "orderHash": order_hash, + "orderMask": expected_order_mask, + "cid": cid, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_cancel_derivative_orders(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + + order_data = basic_composer.order_data( + market_id=derivative_market.id, + subaccount_id=subaccount_id, + order_hash="0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000", + ) + + message = basic_composer.msg_batch_cancel_derivative_orders( + sender=sender, + orders_data=[order_data], + ) + + expected_message = { + "sender": sender, + "data": [json_format.MessageToDict(message=order_data, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_binary_options_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "B2500/INJ" + oracle_symbol = "B2500_1/INJ" + oracle_provider = "Injective" + oracle_scale_factor = 6 + oracle_type = "Band" + quote_denom = "INJ" + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + maker_fee_rate = Decimal("0.001") + taker_fee_rate = Decimal("-0.002") + expiration_timestamp = 1630000000 + settlement_timestamp = 1660000000 + admin = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + message = basic_composer.msg_instant_binary_options_market_launch( + sender=sender, + ticker=ticker, + oracle_symbol=oracle_symbol, + oracle_provider=oracle_provider, + oracle_type=oracle_type, + oracle_scale_factor=oracle_scale_factor, + maker_fee_rate=maker_fee_rate, + taker_fee_rate=taker_fee_rate, + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + admin=admin, + quote_denom=quote_denom, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "oracleSymbol": oracle_symbol, + "oracleProvider": oracle_provider, + "oracleType": oracle_type, + "oracleScaleFactor": oracle_scale_factor, + "makerFeeRate": f"{expected_maker_fee_rate.normalize():f}", + "takerFeeRate": f"{expected_taker_fee_rate.normalize():f}", + "expirationTimestamp": str(expiration_timestamp), + "settlementTimestamp": str(settlement_timestamp), + "admin": admin, + "quoteDenom": quote_token.denom, + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_binary_options_limit_order(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_binary_options_limit_order( + market_id=market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = market.price_to_chain_format(human_readable_value=price) + expected_quantity = market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_binary_options_market_order(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_binary_options_market_order( + market_id=market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = market.price_to_chain_format(human_readable_value=price) + expected_quantity = market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_cancel_derivative_order(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + order_hash = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + cid = "test_cid" + is_conditional = False + is_buy = True + is_market_order = False + + expected_order_mask = basic_composer._order_mask( + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + message = basic_composer.msg_cancel_derivative_order( + market_id=market.id, + sender=sender, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + expected_message = { + "sender": sender, + "marketId": market.id, + "subaccountId": subaccount_id, + "orderHash": order_hash, + "orderMask": expected_order_mask, + "cid": cid, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_subaccount_transfer(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + source_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + destination_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000002" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=amount) + + message = basic_composer.msg_subaccount_transfer( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "sourceSubaccountId": source_subaccount_id, + "destinationSubaccountId": destination_subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_external_transfer(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + source_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + destination_subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=amount) + + message = basic_composer.msg_subaccount_transfer( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "sourceSubaccountId": source_subaccount_id, + "destinationSubaccountId": destination_subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_liquidate_position(self, basic_composer): + market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + order = basic_composer.derivative_order( + market_id=market.id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + margin=Decimal("36.1") * Decimal("100"), + order_type="BUY", + ) + + message = basic_composer.msg_liquidate_position( + sender=sender, + subaccount_id=subaccount_id, + market_id=market.id, + order=order, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "marketId": market.id, + "order": json_format.MessageToDict(message=order, including_default_value_fields=True), + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_emergency_settle_market(self, basic_composer): + market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + + message = basic_composer.msg_emergency_settle_market( + sender=sender, + subaccount_id=subaccount_id, + market_id=market.id, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "marketId": market.id, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_external_transfer(self, basic_composer): + market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + source_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + destination_subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000" + amount = Decimal(100) + + expected_amount = market.margin_to_chain_format(human_readable_value=amount) + + message = basic_composer.msg_increase_position_margin( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + market_id=market.id, + amount=amount, + ) + + expected_message = { + "sender": sender, + "sourceSubaccountId": source_subaccount_id, + "destinationSubaccountId": destination_subaccount_id, + "marketId": market.id, + "amount": f"{expected_amount.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_rewards_opt_out(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + + message = basic_composer.msg_rewards_opt_out( + sender=sender, + ) + + expected_message = { + "sender": sender, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_admin_update_binary_options_market(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + status = "Paused" + settlement_price = Decimal("100.5") + expiration_timestamp = 1630000000 + settlement_timestamp = 1660000000 + + expected_settlement_price = market.price_to_chain_format(human_readable_value=settlement_price) + + message = basic_composer.msg_admin_update_binary_options_market( + sender=sender, + market_id=market.id, + status=status, + settlement_price=settlement_price, + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + ) + + expected_message = { + "sender": sender, + "marketId": market.id, + "settlementPrice": f"{expected_settlement_price.normalize():f}", + "expirationTimestamp": str(expiration_timestamp), + "settlementTimestamp": str(settlement_timestamp), + "status": status, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message diff --git a/tests/test_composer_deprecation_warnings.py b/tests/test_composer_deprecation_warnings.py new file mode 100644 index 00000000..20a86779 --- /dev/null +++ b/tests/test_composer_deprecation_warnings.py @@ -0,0 +1,522 @@ +import warnings +from decimal import Decimal + +import pytest + +from pyinjective.composer import Composer +from pyinjective.core.network import Network +from tests.model_fixtures.markets_fixtures import btc_usdt_perp_market # noqa: F401 +from tests.model_fixtures.markets_fixtures import first_match_bet_market # noqa: F401 +from tests.model_fixtures.markets_fixtures import inj_token # noqa: F401 +from tests.model_fixtures.markets_fixtures import inj_usdt_spot_market # noqa: F401 +from tests.model_fixtures.markets_fixtures import usdt_perp_token # noqa: F401 +from tests.model_fixtures.markets_fixtures import usdt_token # noqa: F401 + + +class TestComposerDeprecationWarnings: + @pytest.fixture + def basic_composer(self, inj_usdt_spot_market, btc_usdt_perp_market, first_match_bet_market): + composer = Composer( + network=Network.devnet().string(), + spot_markets={inj_usdt_spot_market.id: inj_usdt_spot_market}, + derivative_markets={btc_usdt_perp_market.id: btc_usdt_perp_market}, + binary_option_markets={first_match_bet_market.id: first_match_bet_market}, + tokens={ + inj_usdt_spot_market.base_token.symbol: inj_usdt_spot_market.base_token, + inj_usdt_spot_market.quote_token.symbol: inj_usdt_spot_market.quote_token, + btc_usdt_perp_market.quote_token.symbol: btc_usdt_perp_market.quote_token, + }, + ) + + return composer + + def test_msg_deposit_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgDeposit(sender="sender", subaccount_id="subaccount id", amount=1, denom="INJ") + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_deposit instead" + + def test_msg_withdraw_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgWithdraw(sender="sender", subaccount_id="subaccount id", amount=1, denom="USDT") + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_withdraw instead" + + def teste_order_data_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.OrderData( + market_id="market id", + subaccount_id="subaccount id", + order_hash="order hash", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use order_data instead" + + def test_spot_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.SpotOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + is_buy=True, + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use spot_order instead" + + def test_derivative_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.DerivativeOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + is_buy=True, + cid="cid", + leverage=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use derivative_order instead" + + def test_msg_create_spot_limit_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateSpotLimitOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_create_spot_limit_order instead" + ) + + def test_msg_batch_create_spot_limit_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + order = composer.spot_order( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=Decimal(1), + quantity=Decimal(1), + order_type="BUY", + ) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCreateSpotLimitOrders( + sender="sender", + orders=[order], + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_create_spot_limit_orders instead" + ) + + def test_msg_create_spot_market_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateSpotMarketOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + is_buy=True, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_spot_market_order instead" + ) + + def test_msg_cancel_spot_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCancelSpotOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + sender="sender", + subaccount_id="subaccount id", + order_hash="order hash", + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_cancel_spot_order instead" + + def test_msg_batch_cancel_spot_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + orders = [ + composer.order_data( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", + ), + ] + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCancelSpotOrders(sender="sender", data=orders) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_cancel_spot_orders instead" + ) + + def test_msg_batch_update_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchUpdateOrders(sender="sender") + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_batch_update_orders instead" + + def test_msg_privileged_execute_contract_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgPrivilegedExecuteContract( + sender="sender", + contract="contract", + msg="msg", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_privileged_execute_contract instead" + ) + + def test_msg_create_derivative_limit_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateDerivativeLimitOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + leverage=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_derivative_limit_order instead" + ) + + def test_msg_batch_create_derivative_limit_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + order = composer.derivative_order( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=Decimal(1), + quantity=Decimal(1), + margin=Decimal(1), + order_type="BUY", + ) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCreateDerivativeLimitOrders( + sender="sender", + orders=[order], + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_create_derivative_limit_orders instead" + ) + + def test_msg_create_derivative_market_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateDerivativeMarketOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + leverage=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_derivative_market_order instead" + ) + + def test_msg_cancel_derivative_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCancelDerivativeOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + sender="sender", + subaccount_id="subaccount id", + order_hash="order hash", + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_cancel_derivative_order instead" + ) + + def test_msg_batch_cancel_derivative_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + orders = [ + composer.order_data( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", + ), + ] + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCancelDerivativeOrders(sender="sender", data=orders) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_cancel_derivative_orders instead" + ) + + def test_msg_instant_binary_options_market_launch_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgInstantBinaryOptionsMarketLaunch( + sender="sender", + ticker="B2400/INJ", + oracle_symbol="B2400/INJ", + oracle_provider="injective", + oracle_type="Band", + oracle_scale_factor=6, + maker_fee_rate=0.001, + taker_fee_rate=0.001, + expiration_timestamp=1630000000, + settlement_timestamp=1630000000, + quote_denom="inj", + quote_decimals=18, + min_price_tick_size=0.01, + min_quantity_tick_size=0.01, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_instant_binary_options_market_launch instead" + ) + + def test_msg_create_binary_options_limit_order_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgCreateBinaryOptionsLimitOrder( + market_id=market.id, + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + is_buy=True, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_binary_options_limit_order instead" + ) + + def test_msg_create_binary_options_market_order_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgCreateBinaryOptionsMarketOrder( + market_id=market.id, + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + is_buy=True, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_binary_options_market_order instead" + ) + + def test_msg_cancel_binary_options_order_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgCancelBinaryOptionsOrder( + market_id=market.id, + sender="sender", + subaccount_id="subaccount id", + order_hash="order hash", + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_cancel_binary_options_order instead" + ) + + def test_msg_subaccount_transfer_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgSubaccountTransfer( + sender="sender", + source_subaccount_id="source subaccount id", + destination_subaccount_id="destination subaccount id", + amount=1, + denom="INJ", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_subaccount_transfer instead" + + def test_msg_external_transfer_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgExternalTransfer( + sender="sender", + source_subaccount_id="source subaccount id", + destination_subaccount_id="destination subaccount id", + amount=1, + denom="INJ", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_external_transfer instead" + + def test_msg_liquidate_position_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgLiquidatePosition( + sender="sender", + subaccount_id="subaccount id", + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_liquidate_position instead" + + def test_msg_increase_position_margin_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgIncreasePositionMargin( + sender="sender", + source_subaccount_id="source_subaccount id", + destination_subaccount_id="destination_subaccount id", + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + amount=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_increase_position_margin instead" + ) + + def test_msg_rewards_opt_out_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgRewardsOptOut( + sender="sender", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_rewards_opt_out instead" + + def test_msg_admin_update_binary_options_market_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgAdminUpdateBinaryOptionsMarket( + sender="sender", + market_id=market.id, + status="Paused", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_admin_update_binary_options_market instead" + ) diff --git a/tests/test_orderhash.py b/tests/test_orderhash.py index c57b6305..c2940d8d 100644 --- a/tests/test_orderhash.py +++ b/tests/test_orderhash.py @@ -1,3 +1,5 @@ +from decimal import Decimal + from pyinjective import PrivateKey from pyinjective.composer import Composer from pyinjective.core.network import Network @@ -22,23 +24,21 @@ def test_spot_order_hash(self, requests_mock): fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" spot_orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.524, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("0.524"), + quantity=Decimal("0.01"), + order_type="BUY", ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=27.92, - quantity=0.01, - is_buy=False, - is_po=False, + price=Decimal("27.92"), + quantity=Decimal("0.01"), + order_type="SELL", ), ] From 2991ccd3bb69ff0ca2854f4a610345dfd1b8ba98 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 27 Feb 2024 10:50:54 -0300 Subject: [PATCH 23/44] (feat) Adde CodeRabbit configuration file --- .coderabbit.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .coderabbit.yaml diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 00000000..8e534ba3 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,6 @@ +reviews: + auto_review: + base_branches: + - "master" + - "dev" + - "feat/.*" From a435b211596f304bbf24a57e85eb9ef67f0ee13b Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 27 Feb 2024 13:11:47 -0300 Subject: [PATCH 24/44] (fix) Fix in CodeRabbit confir YAML file --- .coderabbit.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 8e534ba3..930db111 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -4,3 +4,5 @@ reviews: - "master" - "dev" - "feat/.*" +chat: + auto_reply: true From 10491af7a003d8d72abb6ccc8f0b328b4d75c46f Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 16 Jan 2024 11:52:25 -0300 Subject: [PATCH 25/44] (fix) Changed version number for dev branch --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 81c1888f..6b7d593e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "injective-py" -version = "1.3.1" +version = "1.4.0-pre" description = "Injective Python SDK, with Exchange API Client" authors = ["Injective Labs "] license = "Apache-2.0" From 4bba9cd192468aba031825e530d63117cc275ec4 Mon Sep 17 00:00:00 2001 From: abel Date: Wed, 17 Jan 2024 10:22:45 -0300 Subject: [PATCH 26/44] (feat) Cleaned up the markets initialization logic --- pyinjective/async_client.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index ec42c2ce..e8da821b 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -9,7 +9,6 @@ import grpc from google.protobuf import json_format -from pyinjective import constant from pyinjective.client.chain.grpc.chain_grpc_auth_api import ChainGrpcAuthApi from pyinjective.client.chain.grpc.chain_grpc_authz_api import ChainGrpcAuthZApi from pyinjective.client.chain.grpc.chain_grpc_bank_api import ChainGrpcBankApi @@ -2659,22 +2658,13 @@ async def _initialize_tokens_and_markets(self): ) for market_info in valid_markets: - ticker = market_info["ticker"] - if "/" in ticker: - base_token_symbol, quote_token_symbol = ticker.split(constant.TICKER_TOKENS_SEPARATOR) - else: - base_token_symbol = market_info["baseTokenMeta"]["symbol"] - quote_token_symbol = market_info["quoteTokenMeta"]["symbol"] - base_token = self._token_representation( - symbol=base_token_symbol, token_meta=market_info["baseTokenMeta"], denom=market_info["baseDenom"], tokens_by_denom=tokens_by_denom, tokens_by_symbol=tokens_by_symbol, ) quote_token = self._token_representation( - symbol=quote_token_symbol, token_meta=market_info["quoteTokenMeta"], denom=market_info["quoteDenom"], tokens_by_denom=tokens_by_denom, @@ -2704,10 +2694,7 @@ async def _initialize_tokens_and_markets(self): ) for market_info in valid_markets: - quote_token_symbol = market_info["quoteTokenMeta"]["symbol"] - quote_token = self._token_representation( - symbol=quote_token_symbol, token_meta=market_info["quoteTokenMeta"], denom=market_info["quoteDenom"], tokens_by_denom=tokens_by_denom, @@ -2769,7 +2756,6 @@ async def _initialize_tokens_and_markets(self): def _token_representation( self, - symbol: str, token_meta: Dict[str, Any], denom: str, tokens_by_denom: Dict[str, Token], @@ -2777,14 +2763,14 @@ def _token_representation( ) -> Token: if denom not in tokens_by_denom: unique_symbol = denom - for symbol_candidate in [symbol, token_meta["symbol"], token_meta["name"]]: + for symbol_candidate in [token_meta["symbol"], token_meta["name"]]: if symbol_candidate not in tokens_by_symbol: unique_symbol = symbol_candidate break token = Token( name=token_meta["name"], - symbol=symbol, + symbol=token_meta["symbol"], denom=denom, address=token_meta["address"], decimals=token_meta["decimals"], From c526eac72b0bb02738793018b31c32f71d0f5dc0 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 6 Feb 2024 16:50:12 -0300 Subject: [PATCH 27/44] (feat) Refactored all examples to remove references to private keys. Added the use of `dotenv` to load private keys into environment variables. Removed `asyncio` package dependency --- examples/SendToInjective.py | 7 +- examples/chain_client/0_LocalOrderHash.py | 8 +- .../13_MsgIncreasePositionMargin.py | 7 +- examples/chain_client/15_MsgWithdraw.py | 7 +- .../chain_client/16_MsgSubaccountTransfer.py | 7 +- .../chain_client/17_MsgBatchUpdateOrders.py | 7 +- examples/chain_client/18_MsgBid.py | 7 +- examples/chain_client/19_MsgGrant.py | 12 +- examples/chain_client/1_MsgSend.py | 7 +- examples/chain_client/20_MsgExec.py | 12 +- examples/chain_client/21_MsgRevoke.py | 12 +- examples/chain_client/22_MsgSendToEth.py | 7 +- .../chain_client/23_MsgRelayPriceFeedPrice.py | 7 +- examples/chain_client/24_MsgRewardsOptOut.py | 7 +- examples/chain_client/25_MsgDelegate.py | 7 +- .../26_MsgWithdrawDelegatorReward.py | 7 +- examples/chain_client/27_Grants.py | 9 +- examples/chain_client/2_MsgDeposit.py | 9 +- examples/chain_client/30_ExternalTransfer.py | 7 +- .../31_MsgCreateBinaryOptionsLimitOrder.py | 7 +- .../32_MsgCreateBinaryOptionsMarketOrder.py | 7 +- .../33_MsgCancelBinaryOptionsOrder.py | 7 +- .../34_MsgAdminUpdateBinaryOptionsMarket.py | 7 +- .../35_MsgInstantBinaryOptionsMarketLaunch.py | 7 +- .../chain_client/36_MsgRelayProviderPrices.py | 7 +- .../chain_client/3_MsgCreateSpotLimitOrder.py | 7 +- .../chain_client/40_MsgExecuteContract.py | 7 +- .../chain_client/41_MsgCreateInsuranceFund.py | 7 +- examples/chain_client/42_MsgUnderwrite.py | 7 +- .../chain_client/43_MsgRequestRedemption.py | 7 +- .../chain_client/44_MessageBroadcaster.py | 7 +- ...45_MessageBroadcasterWithGranteeAccount.py | 10 +- .../46_MessageBroadcasterWithoutSimulation.py | 7 +- ...sterWithGranteeAccountWithoutSimulation.py | 9 +- ...8_WithdrawValidatorCommissionAndRewards.py | 7 +- .../4_MsgCreateSpotMarketOrder.py | 7 +- examples/chain_client/5_MsgCancelSpotOrder.py | 7 +- .../6_MsgCreateDerivativeLimitOrder.py | 7 +- examples/chain_client/71_CreateDenom.py | 7 +- examples/chain_client/72_MsgMint.py | 7 +- examples/chain_client/73_MsgBurn.py | 7 +- .../chain_client/74_MsgSetDenomMetadata.py | 7 +- examples/chain_client/75_MsgChangeAdmin.py | 7 +- .../76_MsgExecuteContractCompat.py | 7 +- .../chain_client/77_MsgLiquidatePosition.py | 7 +- .../7_MsgCreateDerivativeMarketOrder.py | 7 +- .../8_MsgCancelDerivativeOrder.py | 7 +- poetry.lock | 54 +++++--- pyinjective/denoms_devnet.ini | 13 ++ pyinjective/denoms_mainnet.ini | 116 +++++++++++++++--- pyinjective/denoms_testnet.ini | 2 +- pyproject.toml | 3 +- 52 files changed, 445 insertions(+), 97 deletions(-) diff --git a/examples/SendToInjective.py b/examples/SendToInjective.py index b03988b4..23469642 100644 --- a/examples/SendToInjective.py +++ b/examples/SendToInjective.py @@ -1,16 +1,21 @@ import asyncio import json +import os + +import dotenv from pyinjective.core.network import Network from pyinjective.sendtocosmos import Peggo async def main() -> None: + dotenv.load_dotenv() + private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: testnet, mainnet network = Network.testnet() peggo_composer = Peggo(network=network.string()) - private_key = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" ethereum_endpoint = "https://eth-goerli.g.alchemy.com/v2/q-7JVv4mTfsNh1y_djKkKn3maRBGILLL" maxFeePerGas_Gwei = 4 diff --git a/examples/chain_client/0_LocalOrderHash.py b/examples/chain_client/0_LocalOrderHash.py index c81c3e2e..a25398c6 100644 --- a/examples/chain_client/0_LocalOrderHash.py +++ b/examples/chain_client/0_LocalOrderHash.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.async_client import AsyncClient from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE from pyinjective.core.network import Network @@ -10,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/13_MsgIncreasePositionMargin.py b/examples/chain_client/13_MsgIncreasePositionMargin.py index 27d42884..f54910f8 100644 --- a/examples/chain_client/13_MsgIncreasePositionMargin.py +++ b/examples/chain_client/13_MsgIncreasePositionMargin.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/15_MsgWithdraw.py b/examples/chain_client/15_MsgWithdraw.py index 9fc1e359..a8c267d8 100644 --- a/examples/chain_client/15_MsgWithdraw.py +++ b/examples/chain_client/15_MsgWithdraw.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/16_MsgSubaccountTransfer.py b/examples/chain_client/16_MsgSubaccountTransfer.py index 5a18b1dd..d87eb0ed 100644 --- a/examples/chain_client/16_MsgSubaccountTransfer.py +++ b/examples/chain_client/16_MsgSubaccountTransfer.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/17_MsgBatchUpdateOrders.py b/examples/chain_client/17_MsgBatchUpdateOrders.py index 25147452..557ffe46 100644 --- a/examples/chain_client/17_MsgBatchUpdateOrders.py +++ b/examples/chain_client/17_MsgBatchUpdateOrders.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/18_MsgBid.py b/examples/chain_client/18_MsgBid.py index 9e51e075..8e5f8d5e 100644 --- a/examples/chain_client/18_MsgBid.py +++ b/examples/chain_client/18_MsgBid.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/19_MsgGrant.py b/examples/chain_client/19_MsgGrant.py index 0d00d489..32a82fe7 100644 --- a/examples/chain_client/19_MsgGrant.py +++ b/examples/chain_client/19_MsgGrant.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) @@ -30,8 +36,8 @@ async def main() -> None: # GENERIC AUTHZ msg = composer.MsgGrantGeneric( - granter="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", - grantee="inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku", + granter=address.to_acc_bech32(), + grantee=grantee_public_address, msg_type="/injective.exchange.v1beta1.MsgCreateSpotLimitOrder", expire_in=31536000, # 1 year ) diff --git a/examples/chain_client/1_MsgSend.py b/examples/chain_client/1_MsgSend.py index 9b9651f7..6389c8be 100644 --- a/examples/chain_client/1_MsgSend.py +++ b/examples/chain_client/1_MsgSend.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/20_MsgExec.py b/examples/chain_client/20_MsgExec.py index a2876d6a..d5ff2dc5 100644 --- a/examples/chain_client/20_MsgExec.py +++ b/examples/chain_client/20_MsgExec.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,10 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") + granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,15 +26,15 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) # prepare tx msg market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - grantee = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku" - granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + grantee = address.to_acc_bech32() + granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) msg0 = composer.MsgCreateSpotLimitOrder( diff --git a/examples/chain_client/21_MsgRevoke.py b/examples/chain_client/21_MsgRevoke.py index 2cafab7f..82663004 100644 --- a/examples/chain_client/21_MsgRevoke.py +++ b/examples/chain_client/21_MsgRevoke.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + grantee_public_address = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,15 +25,15 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) # prepare tx msg msg = composer.MsgRevoke( - granter="inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku", - grantee="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + granter=address.to_acc_bech32(), + grantee=grantee_public_address, msg_type="/injective.exchange.v1beta1.MsgCreateSpotLimitOrder", ) diff --git a/examples/chain_client/22_MsgSendToEth.py b/examples/chain_client/22_MsgSendToEth.py index 1cb1e677..59bdc877 100644 --- a/examples/chain_client/22_MsgSendToEth.py +++ b/examples/chain_client/22_MsgSendToEth.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv import requests from grpc import RpcError @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/23_MsgRelayPriceFeedPrice.py b/examples/chain_client/23_MsgRelayPriceFeedPrice.py index 38b389de..cc7055c9 100644 --- a/examples/chain_client/23_MsgRelayPriceFeedPrice.py +++ b/examples/chain_client/23_MsgRelayPriceFeedPrice.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/24_MsgRewardsOptOut.py b/examples/chain_client/24_MsgRewardsOptOut.py index bbc8d348..5fa2f429 100644 --- a/examples/chain_client/24_MsgRewardsOptOut.py +++ b/examples/chain_client/24_MsgRewardsOptOut.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/25_MsgDelegate.py b/examples/chain_client/25_MsgDelegate.py index dc95f035..ada14ce0 100644 --- a/examples/chain_client/25_MsgDelegate.py +++ b/examples/chain_client/25_MsgDelegate.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/26_MsgWithdrawDelegatorReward.py b/examples/chain_client/26_MsgWithdrawDelegatorReward.py index 77210421..f9370c23 100644 --- a/examples/chain_client/26_MsgWithdrawDelegatorReward.py +++ b/examples/chain_client/26_MsgWithdrawDelegatorReward.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/27_Grants.py b/examples/chain_client/27_Grants.py index 331980af..9ab27f22 100644 --- a/examples/chain_client/27_Grants.py +++ b/examples/chain_client/27_Grants.py @@ -1,14 +1,19 @@ import asyncio +import os + +import dotenv from pyinjective.async_client import AsyncClient from pyinjective.core.network import Network async def main() -> None: + dotenv.load_dotenv() + granter = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + grantee = os.getenv("INJECTIVE_GRANTEE_PUBLIC_ADDRESS") + network = Network.testnet() client = AsyncClient(network) - granter = "inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku" - grantee = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" msg_type_url = "/injective.exchange.v1beta1.MsgCreateDerivativeLimitOrder" authorizations = await client.fetch_grants(granter=granter, grantee=grantee, msg_type_url=msg_type_url) print(authorizations) diff --git a/examples/chain_client/2_MsgDeposit.py b/examples/chain_client/2_MsgDeposit.py index 9c137b49..80587c55 100644 --- a/examples/chain_client/2_MsgDeposit.py +++ b/examples/chain_client/2_MsgDeposit.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,8 +12,11 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet - network = Network.testnet(node="sentry") + network = Network.testnet() # initialize grpc client client = AsyncClient(network) @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/30_ExternalTransfer.py b/examples/chain_client/30_ExternalTransfer.py index d657c15a..7ab6e0f2 100644 --- a/examples/chain_client/30_ExternalTransfer.py +++ b/examples/chain_client/30_ExternalTransfer.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py index 137529ea..57f5537b 100644 --- a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py +++ b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -12,6 +14,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -21,7 +26,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py index 67004f17..473e8e53 100644 --- a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py +++ b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py index 2631ab26..15159f00 100644 --- a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py +++ b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py index d9eb1e18..55c308be 100644 --- a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py +++ b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py index e0881db5..7e865320 100644 --- a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py +++ b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/36_MsgRelayProviderPrices.py b/examples/chain_client/36_MsgRelayProviderPrices.py index 0fb26b4f..4ee5fc3f 100644 --- a/examples/chain_client/36_MsgRelayProviderPrices.py +++ b/examples/chain_client/36_MsgRelayProviderPrices.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/3_MsgCreateSpotLimitOrder.py index 8d873354..dd06672a 100644 --- a/examples/chain_client/3_MsgCreateSpotLimitOrder.py +++ b/examples/chain_client/3_MsgCreateSpotLimitOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/40_MsgExecuteContract.py b/examples/chain_client/40_MsgExecuteContract.py index fef42954..f2d1b719 100644 --- a/examples/chain_client/40_MsgExecuteContract.py +++ b/examples/chain_client/40_MsgExecuteContract.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/41_MsgCreateInsuranceFund.py b/examples/chain_client/41_MsgCreateInsuranceFund.py index b402dc26..74f94bfa 100644 --- a/examples/chain_client/41_MsgCreateInsuranceFund.py +++ b/examples/chain_client/41_MsgCreateInsuranceFund.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/42_MsgUnderwrite.py b/examples/chain_client/42_MsgUnderwrite.py index 9a14b3ce..20c65a64 100644 --- a/examples/chain_client/42_MsgUnderwrite.py +++ b/examples/chain_client/42_MsgUnderwrite.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/43_MsgRequestRedemption.py b/examples/chain_client/43_MsgRequestRedemption.py index 6ba0fe31..4413044b 100644 --- a/examples/chain_client/43_MsgRequestRedemption.py +++ b/examples/chain_client/43_MsgRequestRedemption.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/44_MessageBroadcaster.py b/examples/chain_client/44_MessageBroadcaster.py index a9bb1f68..114a8700 100644 --- a/examples/chain_client/44_MessageBroadcaster.py +++ b/examples/chain_client/44_MessageBroadcaster.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network @@ -8,10 +11,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py b/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py index 59c04af2..8c0166e2 100644 --- a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py +++ b/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.async_client import AsyncClient from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -9,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") + granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) @@ -18,7 +25,6 @@ async def main() -> None: await client.sync_timeout_height() # load account - private_key_in_hexa = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() @@ -30,7 +36,7 @@ async def main() -> None: # prepare tx msg market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) diff --git a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py b/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py index 908a4579..e6e87c5a 100644 --- a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py +++ b/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk from pyinjective.core.network import Network @@ -8,10 +11,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( network=network, diff --git a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py b/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py index ebae28ab..b95114b7 100644 --- a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py +++ b/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py @@ -1,6 +1,9 @@ import asyncio +import os import uuid +import dotenv + from pyinjective.async_client import AsyncClient from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -9,6 +12,10 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_GRANTEE_PRIVATE_KEY") + granter_inj_address = os.getenv("INJECTIVE_GRANTER_PUBLIC_ADDRESS") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) @@ -18,7 +25,6 @@ async def main() -> None: await client.sync_timeout_height() # load account - private_key_in_hexa = "5d386fbdbf11f1141010f81a46b40f94887367562bd33b452bbaa6ce1cd1381e" priv_key = PrivateKey.from_hex(private_key_in_hexa) pub_key = priv_key.to_public_key() address = pub_key.to_address() @@ -30,7 +36,6 @@ async def main() -> None: # prepare tx msg market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - granter_inj_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) diff --git a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py b/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py index b46ca371..2f67f6c4 100644 --- a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py +++ b/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + """For a validator to withdraw his rewards & commissions simultaneously""" # select network: local, testnet, mainnet network = Network.testnet() @@ -22,7 +27,7 @@ async def main() -> None: # load account # private key is that from the validator's wallet - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/4_MsgCreateSpotMarketOrder.py index d689362f..06a42a96 100644 --- a/examples/chain_client/4_MsgCreateSpotMarketOrder.py +++ b/examples/chain_client/4_MsgCreateSpotMarketOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/5_MsgCancelSpotOrder.py b/examples/chain_client/5_MsgCancelSpotOrder.py index a6fabc01..63167309 100644 --- a/examples/chain_client/5_MsgCancelSpotOrder.py +++ b/examples/chain_client/5_MsgCancelSpotOrder.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py index b875d339..e46f1acb 100644 --- a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/71_CreateDenom.py b/examples/chain_client/71_CreateDenom.py index 61e76dbf..0662439a 100644 --- a/examples/chain_client/71_CreateDenom.py +++ b/examples/chain_client/71_CreateDenom.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/72_MsgMint.py b/examples/chain_client/72_MsgMint.py index e96bad93..d38449be 100644 --- a/examples/chain_client/72_MsgMint.py +++ b/examples/chain_client/72_MsgMint.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/73_MsgBurn.py b/examples/chain_client/73_MsgBurn.py index cff5a1b4..441f4ee8 100644 --- a/examples/chain_client/73_MsgBurn.py +++ b/examples/chain_client/73_MsgBurn.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( network=network, diff --git a/examples/chain_client/74_MsgSetDenomMetadata.py b/examples/chain_client/74_MsgSetDenomMetadata.py index 58fa30c0..367649e0 100644 --- a/examples/chain_client/74_MsgSetDenomMetadata.py +++ b/examples/chain_client/74_MsgSetDenomMetadata.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( network=network, diff --git a/examples/chain_client/75_MsgChangeAdmin.py b/examples/chain_client/75_MsgChangeAdmin.py index 2abc6ec6..d1a1ba46 100644 --- a/examples/chain_client/75_MsgChangeAdmin.py +++ b/examples/chain_client/75_MsgChangeAdmin.py @@ -1,4 +1,7 @@ import asyncio +import os + +import dotenv from pyinjective.composer import Composer as ProtoMsgComposer from pyinjective.core.broadcaster import MsgBroadcasterWithPk @@ -7,10 +10,12 @@ async def main() -> None: + dotenv.load_dotenv() + private_key_in_hexa = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() composer = ProtoMsgComposer(network=network.string()) - private_key_in_hexa = "f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3" message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( network=network, diff --git a/examples/chain_client/76_MsgExecuteContractCompat.py b/examples/chain_client/76_MsgExecuteContractCompat.py index 978ff115..892c125f 100644 --- a/examples/chain_client/76_MsgExecuteContractCompat.py +++ b/examples/chain_client/76_MsgExecuteContractCompat.py @@ -1,6 +1,8 @@ import asyncio import json +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/77_MsgLiquidatePosition.py b/examples/chain_client/77_MsgLiquidatePosition.py index 65e7f12b..6dcbacfb 100644 --- a/examples/chain_client/77_MsgLiquidatePosition.py +++ b/examples/chain_client/77_MsgLiquidatePosition.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py index 744b5ff9..e7e06c62 100644 --- a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py +++ b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py @@ -1,6 +1,8 @@ import asyncio +import os import uuid +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -11,6 +13,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -20,7 +25,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/examples/chain_client/8_MsgCancelDerivativeOrder.py b/examples/chain_client/8_MsgCancelDerivativeOrder.py index b784b536..6a59167a 100644 --- a/examples/chain_client/8_MsgCancelDerivativeOrder.py +++ b/examples/chain_client/8_MsgCancelDerivativeOrder.py @@ -1,5 +1,7 @@ import asyncio +import os +import dotenv from grpc import RpcError from pyinjective.async_client import AsyncClient @@ -10,6 +12,9 @@ async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + # select network: local, testnet, mainnet network = Network.testnet() @@ -19,7 +24,7 @@ async def main() -> None: await client.sync_timeout_height() # load account - priv_key = PrivateKey.from_hex("f9db9bf330e23cb7839039e944adef6e9df447b90b503d5b4464c90bea9022f3") + priv_key = PrivateKey.from_hex(configured_private_key) pub_key = priv_key.to_public_key() address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) diff --git a/poetry.lock b/poetry.lock index 9d754939..72bd53e3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1395,13 +1395,13 @@ test = ["eth-utils (>=1.0.1,<3)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>= [[package]] name = "identify" -version = "2.5.34" +version = "2.5.33" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.34-py2.py3-none-any.whl", hash = "sha256:a4316013779e433d08b96e5eabb7f641e6c7942e4ab5d4c509ebd2e7a8994aed"}, - {file = "identify-2.5.34.tar.gz", hash = "sha256:ee17bc9d499899bc9eaec1ac7bf2dc9eedd480db9d88b96d123d3b64a9d34f5d"}, + {file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"}, + {file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"}, ] [package.extras] @@ -1785,13 +1785,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.6.1" +version = "3.6.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" files = [ - {file = "pre_commit-3.6.1-py2.py3-none-any.whl", hash = "sha256:9fe989afcf095d2c4796ce7c553cf28d4d4a9b9346de3cda079bcf40748454a4"}, - {file = "pre_commit-3.6.1.tar.gz", hash = "sha256:c90961d8aa706f75d60935aba09469a6b0bcb8345f127c3fbee4bdc5f114cf4b"}, + {file = "pre_commit-3.6.0-py2.py3-none-any.whl", hash = "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376"}, + {file = "pre_commit-3.6.0.tar.gz", hash = "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d"}, ] [package.dependencies] @@ -1912,13 +1912,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" -version = "8.0.0" +version = "7.4.4" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"}, - {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"}, + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, ] [package.dependencies] @@ -1926,7 +1926,7 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=1.3.0,<2.0" +pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] @@ -1934,17 +1934,17 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no [[package]] name = "pytest-asyncio" -version = "0.23.5" +version = "0.23.4" description = "Pytest support for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-asyncio-0.23.5.tar.gz", hash = "sha256:3a048872a9c4ba14c3e90cc1aa20cbc2def7d01c7c8db3777ec281ba9c057675"}, - {file = "pytest_asyncio-0.23.5-py3-none-any.whl", hash = "sha256:4e7093259ba018d58ede7d5315131d21923a60f8a6e9ee266ce1589685c89eac"}, + {file = "pytest-asyncio-0.23.4.tar.gz", hash = "sha256:2143d9d9375bf372a73260e4114541485e84fca350b0b6b92674ca56ff5f7ea2"}, + {file = "pytest_asyncio-0.23.4-py3-none-any.whl", hash = "sha256:b0079dfac14b60cd1ce4691fbfb1748fe939db7d0234b5aba97197d10fbe0fef"}, ] [package.dependencies] -pytest = ">=7.0.0,<9" +pytest = ">=7.0.0,<8" [package.extras] docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] @@ -1982,6 +1982,20 @@ files = [ [package.dependencies] pytest = ">=3.6.0" +[[package]] +name = "python-dotenv" +version = "1.0.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "pyunormalize" version = "15.1.0" @@ -2371,18 +2385,18 @@ files = [ [[package]] name = "setuptools" -version = "69.1.0" +version = "69.0.3" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"}, - {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"}, + {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, + {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] @@ -2698,4 +2712,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "7d6d14d38c3b61b57e268c236168e21a1b90e7fa0e36814a44468cace4f699a1" +content-hash = "9e0468421485c45e3ce0e68578905dac1e50a1ed1cae8f8c6a19c91b67f36ca0" diff --git a/pyinjective/denoms_devnet.ini b/pyinjective/denoms_devnet.ini index 62979d72..3c422179 100644 --- a/pyinjective/denoms_devnet.ini +++ b/pyinjective/denoms_devnet.ini @@ -169,6 +169,15 @@ min_display_price_tick_size = 0.001 min_quantity_tick_size = 10000000000000 min_display_quantity_tick_size = 0.00001 +[0x2d3b8d8833dda54a717adea9119134556848105fd6028e9a4a526e4e5a122a57] +description = 'Devnet Spot KIRA/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000 +min_display_quantity_tick_size = 1000 + [0x1422a13427d5eabd4d8de7907c8340f7e58cb15553a9fd4ad5c90406561886f9] description = 'Devnet Derivative COMP/USDT PERP' base = 0 @@ -291,6 +300,10 @@ decimals = 18 peggy_denom = inj decimals = 18 +[KIRA] +peggy_denom = factory/inj1xy3kvlr4q4wdd6lrelsrw2fk2ged0any44hhwq/KIRA +decimals = 6 + [LINK] peggy_denom = peggy0x514910771AF9Ca656af840dff83E8264EcF986CA decimals = 18 diff --git a/pyinjective/denoms_mainnet.ini b/pyinjective/denoms_mainnet.ini index b2430837..9d88ca6d 100644 --- a/pyinjective/denoms_mainnet.ini +++ b/pyinjective/denoms_mainnet.ini @@ -682,6 +682,24 @@ min_display_price_tick_size = 0.000001 min_quantity_tick_size = 10000000000000000000 min_display_quantity_tick_size = 10 +[0x0a1366c8b05658c0ccca6064e4b20aacd5ad350c02debd6ec0f4dc9178145d14] +description = 'Mainnet Spot GYEN/USDT' +base = 6 +quote = 6 +min_price_tick_size = 0.000001 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 100000000 +min_display_quantity_tick_size = 100 + +[0x9c8a91a894f773792b1e8d0b6a8224a6b748753738e9945020ee566266f817be] +description = 'Mainnet Spot USDCnb/USDT' +base = 6 +quote = 6 +min_price_tick_size = 0.0001 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 100000 +min_display_quantity_tick_size = 0.1 + [0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce] description = 'Mainnet Derivative BTC/USDT PERP' base = 0 @@ -736,14 +754,23 @@ min_display_price_tick_size = 0.001 min_quantity_tick_size = 0.01 min_display_quantity_tick_size = 0.01 +[0xcf18525b53e54ad7d27477426ade06d69d8d56d2f3bf35fe5ce2ad9eb97c2fbc] +description = 'Mainnet Derivative OSMO/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + [0x06c5a306492ddc2b8dc56969766959163287ed68a6b59baa2f42330dda0aebe0] description = 'Mainnet Derivative SOL/USDT PERP' base = 0 quote = 6 min_price_tick_size = 10000 min_display_price_tick_size = 0.01 -min_quantity_tick_size = 0.1 -min_display_quantity_tick_size = 0.1 +min_quantity_tick_size = 0.001 +min_display_quantity_tick_size = 0.001 [0xcd0c859a99f26bb3530e21890937ed77d20754aa7825a599c71710514fc125ef] description = 'Mainnet Derivative 1MPEPE/USDT PERP' @@ -817,6 +844,51 @@ min_display_price_tick_size = 0.00001 min_quantity_tick_size = 1 min_display_quantity_tick_size = 1 +[0x30a1463cfb4c393c80e257ab93118cecd73c1e632dc4d2d31c12a51bc0a70bd7] +description = 'Mainnet Derivative AVAX/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.01 +min_quantity_tick_size = 0.01 +min_display_quantity_tick_size = 0.01 + +[0x18b2ca44b3d20a3b87c87d3765669b09b73b5e900693896c08394c70e79ab1e7] +description = 'Mainnet Derivative SUI/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + +[0x1a6d3a59f45904e0a4a2eed269fc2f552e7e407ac90aaaeb602c31b017573f88] +description = 'Mainnet Derivative WIF/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 100 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1 +min_display_quantity_tick_size = 1 + +[0x48fcecd66ebabbf5a331178ec693b261dfae66ddfe6f552d7446744c6e78046c] +description = 'Mainnet Derivative OP/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + +[0x6ddf0b8fbbd888981aafdae9fc967a12c6777aac4dd100a8257b8755c0c4b7d5] +description = 'Mainnet Derivative ARB/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 1000 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 0.1 +min_display_quantity_tick_size = 0.1 + [AAVE] peggy_denom = peggy0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9 decimals = 18 @@ -845,6 +917,10 @@ decimals = 6 peggy_denom = peggy0xBB0E17EF65F82Ab018d8EDd776e8DD940327B28b decimals = 18 +[Axelar Wrapped USDC] +peggy_denom = ibc/7E1AF94AD246BE522892751046F0C959B768642E5671CC3742264068D49553C0 +decimals = 6 + [BRETT] peggy_denom = factory/inj13jjdsa953w03dvecsr43dj5r6a2vzt7n0spncv/brett decimals = 6 @@ -885,6 +961,10 @@ decimals = 6 peggy_denom = peggy0xc944E90C64B2c07662A292be6244BDf05Cda44a7 decimals = 18 +[GYEN] +peggy_denom = peggy0xC08512927D12348F6620a698105e1BAac6EcD911 +decimals = 6 + [HUAHUA] peggy_denom = ibc/E7807A46C0B7B44B350DA58F51F278881B863EC4DCA94635DAB39E52C30766CB decimals = 6 @@ -933,6 +1013,10 @@ decimals = 18 peggy_denom = factory/inj1xtel2knkt8hmc9dnzpjz6kdmacgcfmlv5f308w/ninja decimals = 6 +[Noble USD Coin] +peggy_denom = ibc/2CBC2EA121AE42563B08028466F37B600F2D7D4282342DE938283CC3FB2BC00E +decimals = 6 + [ORAI] peggy_denom = ibc/C20C0A822BD22B2CEF0D067400FCCFB6FAEEE9E91D360B4E0725BD522302D565 decimals = 6 @@ -973,14 +1057,6 @@ decimals = 6 peggy_denom = peggy0x6B3595068778DD592e39A122f4f5a5cF09C90fE2 decimals = 18 -[SteadyBTC] -peggy_denom = peggy0x4986fD36b6b16f49b43282Ee2e24C5cF90ed166d -decimals = 18 - -[SteadyETH] -peggy_denom = peggy0x3F07A84eCdf494310D397d24c1C78B041D2fa622 -decimals = 18 - [TALIS] peggy_denom = factory/inj1maeyvxfamtn8lfyxpjca8kuvauuf2qeu6gtxm3/Talis decimals = 6 @@ -997,12 +1073,12 @@ decimals = 18 peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj1q6zlut7gtkzknkk773jecujwsdkgq882akqksk decimals = 6 -[USDC] -peggy_denom = peggy0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 +[USD Coin (Wormhole from Solana)] +peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj12pwnhtv7yat2s30xuf4gdk9qm85v4j3e60dgvu decimals = 6 -[USDCso] -peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj12pwnhtv7yat2s30xuf4gdk9qm85v4j3e60dgvu +[USDC] +peggy_denom = peggy0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 decimals = 6 [USDT] @@ -1049,10 +1125,6 @@ decimals = 6 peggy_denom = peggy0xb2617246d0c6c0087f18703d576831899ca94f01 decimals = 18 -[axlUSDC] -peggy_denom = ibc/7E1AF94AD246BE522892751046F0C959B768642E5671CC3742264068D49553C0 -decimals = 6 - [nINJ] peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj13xlpypcwl5fuc84uhqzzqumnrcfpptyl6w3vrf decimals = 18 @@ -1060,3 +1132,11 @@ decimals = 18 [stINJ] peggy_denom = ibc/AC87717EA002B0123B10A05063E69BCA274BA2C44D842AEEB41558D2856DCE93 decimals = 18 + +[steadyBTC] +peggy_denom = peggy0x4986fD36b6b16f49b43282Ee2e24C5cF90ed166d +decimals = 18 + +[steadyETH] +peggy_denom = peggy0x3F07A84eCdf494310D397d24c1C78B041D2fa622 +decimals = 18 diff --git a/pyinjective/denoms_testnet.ini b/pyinjective/denoms_testnet.ini index d81212d8..fd823592 100644 --- a/pyinjective/denoms_testnet.ini +++ b/pyinjective/denoms_testnet.ini @@ -397,7 +397,7 @@ decimals = 8 peggy_denom = inj decimals = 18 -[MITOTEST1] +[MitoTest1] peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/mitotest1 decimals = 18 diff --git a/pyproject.toml b/pyproject.toml index 6b7d593e..0838ac19 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ websockets = "*" web3 = "^6.0" [tool.poetry.group.test.dependencies] -pytest = "*" +pytest = "<8" pytest-asyncio = "*" pytest-grpc = "*" requests-mock = "*" @@ -51,6 +51,7 @@ pre-commit = "^3.4.0" flakeheaven = "^3.3.0" isort = "^5.12.0" black = "^23.9.1" +python-dotenv = "^1.0.1" [tool.flakeheaven] From f02435c015d229670e047dab92139fca08113fcb Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 16 Jan 2024 11:52:25 -0300 Subject: [PATCH 28/44] (fix) Changed version number for dev branch --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0838ac19..c983dd07 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ websockets = "*" web3 = "^6.0" [tool.poetry.group.test.dependencies] -pytest = "<8" +pytest = "*" pytest-asyncio = "*" pytest-grpc = "*" requests-mock = "*" From 7573faad71b704cb9ab56b833bd6a9a2a04de990 Mon Sep 17 00:00:00 2001 From: abel Date: Mon, 12 Feb 2024 17:32:02 -0300 Subject: [PATCH 29/44] (fix) Updated dependencies versions in poetry.lock --- poetry.lock | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/poetry.lock b/poetry.lock index 72bd53e3..082dfb36 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1395,13 +1395,13 @@ test = ["eth-utils (>=1.0.1,<3)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>= [[package]] name = "identify" -version = "2.5.33" +version = "2.5.34" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"}, - {file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"}, + {file = "identify-2.5.34-py2.py3-none-any.whl", hash = "sha256:a4316013779e433d08b96e5eabb7f641e6c7942e4ab5d4c509ebd2e7a8994aed"}, + {file = "identify-2.5.34.tar.gz", hash = "sha256:ee17bc9d499899bc9eaec1ac7bf2dc9eedd480db9d88b96d123d3b64a9d34f5d"}, ] [package.extras] @@ -1785,13 +1785,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.6.0" +version = "3.6.1" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" files = [ - {file = "pre_commit-3.6.0-py2.py3-none-any.whl", hash = "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376"}, - {file = "pre_commit-3.6.0.tar.gz", hash = "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d"}, + {file = "pre_commit-3.6.1-py2.py3-none-any.whl", hash = "sha256:9fe989afcf095d2c4796ce7c553cf28d4d4a9b9346de3cda079bcf40748454a4"}, + {file = "pre_commit-3.6.1.tar.gz", hash = "sha256:c90961d8aa706f75d60935aba09469a6b0bcb8345f127c3fbee4bdc5f114cf4b"}, ] [package.dependencies] @@ -1912,13 +1912,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" -version = "7.4.4" +version = "8.0.0" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, + {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"}, + {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"}, ] [package.dependencies] @@ -1926,7 +1926,7 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" +pluggy = ">=1.3.0,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] @@ -1934,17 +1934,17 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no [[package]] name = "pytest-asyncio" -version = "0.23.4" +version = "0.23.5" description = "Pytest support for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-asyncio-0.23.4.tar.gz", hash = "sha256:2143d9d9375bf372a73260e4114541485e84fca350b0b6b92674ca56ff5f7ea2"}, - {file = "pytest_asyncio-0.23.4-py3-none-any.whl", hash = "sha256:b0079dfac14b60cd1ce4691fbfb1748fe939db7d0234b5aba97197d10fbe0fef"}, + {file = "pytest-asyncio-0.23.5.tar.gz", hash = "sha256:3a048872a9c4ba14c3e90cc1aa20cbc2def7d01c7c8db3777ec281ba9c057675"}, + {file = "pytest_asyncio-0.23.5-py3-none-any.whl", hash = "sha256:4e7093259ba018d58ede7d5315131d21923a60f8a6e9ee266ce1589685c89eac"}, ] [package.dependencies] -pytest = ">=7.0.0,<8" +pytest = ">=7.0.0,<9" [package.extras] docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] @@ -2385,18 +2385,18 @@ files = [ [[package]] name = "setuptools" -version = "69.0.3" +version = "69.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, - {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, + {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"}, + {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] @@ -2712,4 +2712,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "9e0468421485c45e3ce0e68578905dac1e50a1ed1cae8f8c6a19c91b67f36ca0" +content-hash = "531c4e91b09feb8097149a63a8cfde93152cd904df0f6616790d51ca8838dfe0" From 9235c41c507f39da09abbcb64f60c2e538e297bf Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 6 Feb 2024 16:50:12 -0300 Subject: [PATCH 30/44] (feat) Refactored all examples to remove references to private keys. Added the use of `dotenv` to load private keys into environment variables. Removed `asyncio` package dependency --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c983dd07..0838ac19 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ websockets = "*" web3 = "^6.0" [tool.poetry.group.test.dependencies] -pytest = "*" +pytest = "<8" pytest-asyncio = "*" pytest-grpc = "*" requests-mock = "*" From 9ff8783d5898b0198c8ce4b583dad9ea28903c0c Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 16 Jan 2024 11:52:25 -0300 Subject: [PATCH 31/44] (fix) Changed version number for dev branch --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0838ac19..c983dd07 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ websockets = "*" web3 = "^6.0" [tool.poetry.group.test.dependencies] -pytest = "<8" +pytest = "*" pytest-asyncio = "*" pytest-grpc = "*" requests-mock = "*" From 51f17520f3ede2efcf51ac48468a1b4f5052e4ad Mon Sep 17 00:00:00 2001 From: abel Date: Fri, 9 Feb 2024 00:14:58 -0300 Subject: [PATCH 32/44] (feat) Added support for all `distribution` module queries. Added also new example scripts for all queries and unit tests --- .../1_ValidatorDistributionInfo.py | 16 + .../2_ValidatorOutstandingRewards.py | 16 + .../distribution/3_ValidatorCommission.py | 16 + .../distribution/4_ValidatorSlashes.py | 20 ++ .../distribution/5_DelegationRewards.py | 19 + .../distribution/6_DelegationTotalRewards.py | 18 + .../distribution/7_DelegatorValidators.py | 18 + .../8_DelegatorWithdrawAddress.py | 18 + .../distribution/9_CommunityPool.py | 15 + pyinjective/async_client.py | 67 ++++ .../chain/grpc/chain_grpc_distribution_api.py | 109 ++++++ ...y => configurable_authz_query_servicer.py} | 0 ...onfigurable_distribution_query_servicer.py | 69 ++++ .../grpc/test_chain_grpc_distribution_api.py | 338 ++++++++++++++++++ 14 files changed, 739 insertions(+) create mode 100644 examples/chain_client/distribution/1_ValidatorDistributionInfo.py create mode 100644 examples/chain_client/distribution/2_ValidatorOutstandingRewards.py create mode 100644 examples/chain_client/distribution/3_ValidatorCommission.py create mode 100644 examples/chain_client/distribution/4_ValidatorSlashes.py create mode 100644 examples/chain_client/distribution/5_DelegationRewards.py create mode 100644 examples/chain_client/distribution/6_DelegationTotalRewards.py create mode 100644 examples/chain_client/distribution/7_DelegatorValidators.py create mode 100644 examples/chain_client/distribution/8_DelegatorWithdrawAddress.py create mode 100644 examples/chain_client/distribution/9_CommunityPool.py create mode 100644 pyinjective/client/chain/grpc/chain_grpc_distribution_api.py rename tests/client/chain/grpc/{configurable_autz_query_servicer.py => configurable_authz_query_servicer.py} (100%) create mode 100644 tests/client/chain/grpc/configurable_distribution_query_servicer.py create mode 100644 tests/client/chain/grpc/test_chain_grpc_distribution_api.py diff --git a/examples/chain_client/distribution/1_ValidatorDistributionInfo.py b/examples/chain_client/distribution/1_ValidatorDistributionInfo.py new file mode 100644 index 00000000..13161630 --- /dev/null +++ b/examples/chain_client/distribution/1_ValidatorDistributionInfo.py @@ -0,0 +1,16 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + distribution_info = await client.fetch_validator_distribution_info(validator_address=validator_address) + print(distribution_info) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/2_ValidatorOutstandingRewards.py b/examples/chain_client/distribution/2_ValidatorOutstandingRewards.py new file mode 100644 index 00000000..31833682 --- /dev/null +++ b/examples/chain_client/distribution/2_ValidatorOutstandingRewards.py @@ -0,0 +1,16 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + rewards = await client.fetch_validator_outstanding_rewards(validator_address=validator_address) + print(rewards) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/3_ValidatorCommission.py b/examples/chain_client/distribution/3_ValidatorCommission.py new file mode 100644 index 00000000..a82e191b --- /dev/null +++ b/examples/chain_client/distribution/3_ValidatorCommission.py @@ -0,0 +1,16 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + commission = await client.fetch_validator_commission(validator_address=validator_address) + print(commission) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/4_ValidatorSlashes.py b/examples/chain_client/distribution/4_ValidatorSlashes.py new file mode 100644 index 00000000..08dbfea1 --- /dev/null +++ b/examples/chain_client/distribution/4_ValidatorSlashes.py @@ -0,0 +1,20 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + limit = 2 + pagination = PaginationOption(limit=limit) + validator_address = "injvaloper1jue5dpr9lerjn6wlwtrywxrsenrf28ru89z99z" + contracts = await client.fetch_validator_slashes(validator_address=validator_address, pagination=pagination) + print(contracts) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/5_DelegationRewards.py b/examples/chain_client/distribution/5_DelegationRewards.py new file mode 100644 index 00000000..da112263 --- /dev/null +++ b/examples/chain_client/distribution/5_DelegationRewards.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + validator_address = "injvaloper156t3yxd4udv0h9gwagfcmwnmm3quy0nph7tyh5" + rewards = await client.fetch_delegation_rewards( + delegator_address=delegator_address, validator_address=validator_address + ) + print(rewards) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/6_DelegationTotalRewards.py b/examples/chain_client/distribution/6_DelegationTotalRewards.py new file mode 100644 index 00000000..c67dc94f --- /dev/null +++ b/examples/chain_client/distribution/6_DelegationTotalRewards.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + rewards = await client.fetch_delegation_total_rewards( + delegator_address=delegator_address, + ) + print(rewards) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/7_DelegatorValidators.py b/examples/chain_client/distribution/7_DelegatorValidators.py new file mode 100644 index 00000000..f03fb8ec --- /dev/null +++ b/examples/chain_client/distribution/7_DelegatorValidators.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + validators = await client.fetch_delegator_validators( + delegator_address=delegator_address, + ) + print(validators) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/8_DelegatorWithdrawAddress.py b/examples/chain_client/distribution/8_DelegatorWithdrawAddress.py new file mode 100644 index 00000000..d3c27091 --- /dev/null +++ b/examples/chain_client/distribution/8_DelegatorWithdrawAddress.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + delegator_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + withdraw_address = await client.fetch_delegator_withdraw_address( + delegator_address=delegator_address, + ) + print(withdraw_address) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/9_CommunityPool.py b/examples/chain_client/distribution/9_CommunityPool.py new file mode 100644 index 00000000..7a803d03 --- /dev/null +++ b/examples/chain_client/distribution/9_CommunityPool.py @@ -0,0 +1,15 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + community_pool = await client.fetch_community_pool() + print(community_pool) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index e8da821b..dea12f12 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -12,6 +12,7 @@ from pyinjective.client.chain.grpc.chain_grpc_auth_api import ChainGrpcAuthApi from pyinjective.client.chain.grpc.chain_grpc_authz_api import ChainGrpcAuthZApi from pyinjective.client.chain.grpc.chain_grpc_bank_api import ChainGrpcBankApi +from pyinjective.client.chain.grpc.chain_grpc_distribution_api import ChainGrpcDistributionApi from pyinjective.client.chain.grpc.chain_grpc_token_factory_api import ChainGrpcTokenFactoryApi from pyinjective.client.chain.grpc.chain_grpc_wasm_api import ChainGrpcWasmApi from pyinjective.client.chain.grpc_stream.chain_grpc_chain_stream import ChainGrpcChainStream @@ -178,6 +179,12 @@ def __init__( metadata_query_provider=self._chain_cookie_metadata_requestor ), ) + self.distribution_api = ChainGrpcDistributionApi( + channel=self.chain_channel, + metadata_provider=lambda: self.network.chain_metadata( + metadata_query_provider=self._chain_cookie_metadata_requestor + ), + ) self.token_factory_api = ChainGrpcTokenFactoryApi( channel=self.chain_channel, metadata_provider=lambda: self.network.chain_metadata( @@ -572,6 +579,66 @@ async def fetch_send_enabled( ) -> Dict[str, Any]: return await self.bank_api.fetch_send_enabled(denoms=denoms, pagination=pagination) + async def fetch_validator_distribution_info(self, validator_address: str) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_distribution_info(validator_address=validator_address) + + async def fetch_validator_outstanding_rewards(self, validator_address: str) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_outstanding_rewards(validator_address=validator_address) + + async def fetch_validator_commission(self, validator_address: str) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_commission(validator_address=validator_address) + + async def fetch_validator_slashes( + self, + validator_address: str, + starting_height: Optional[int] = None, + ending_height: Optional[int] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_validator_slashes( + validator_address=validator_address, + starting_height=starting_height, + ending_height=ending_height, + pagination=pagination, + ) + + async def fetch_delegation_rewards( + self, + delegator_address: str, + validator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegation_rewards( + delegator_address=delegator_address, + validator_address=validator_address, + ) + + async def fetch_delegation_total_rewards( + self, + delegator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegation_total_rewards( + delegator_address=delegator_address, + ) + + async def fetch_delegator_validators( + self, + delegator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegator_validators( + delegator_address=delegator_address, + ) + + async def fetch_delegator_withdraw_address( + self, + delegator_address: str, + ) -> Dict[str, Any]: + return await self.distribution_api.fetch_delegator_withdraw_address( + delegator_address=delegator_address, + ) + + async def fetch_community_pool(self) -> Dict[str, Any]: + return await self.distribution_api.fetch_community_pool() + # Injective Exchange client methods # Auction RPC diff --git a/pyinjective/client/chain/grpc/chain_grpc_distribution_api.py b/pyinjective/client/chain/grpc/chain_grpc_distribution_api.py new file mode 100644 index 00000000..e7da0966 --- /dev/null +++ b/pyinjective/client/chain/grpc/chain_grpc_distribution_api.py @@ -0,0 +1,109 @@ +from typing import Any, Callable, Dict, Optional + +from grpc.aio import Channel + +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + query_pb2 as distribution_query_pb, + query_pb2_grpc as distribution_query_grpc, +) +from pyinjective.utils.grpc_api_request_assistant import GrpcApiRequestAssistant + + +class ChainGrpcDistributionApi: + def __init__(self, channel: Channel, metadata_provider: Callable): + self._stub = distribution_query_grpc.QueryStub(channel) + self._assistant = GrpcApiRequestAssistant(metadata_provider=metadata_provider) + + async def fetch_module_params(self) -> Dict[str, Any]: + request = distribution_query_pb.QueryParamsRequest() + response = await self._execute_call(call=self._stub.Params, request=request) + + return response + + async def fetch_validator_distribution_info(self, validator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryValidatorDistributionInfoRequest(validator_address=validator_address) + response = await self._execute_call(call=self._stub.ValidatorDistributionInfo, request=request) + + return response + + async def fetch_validator_outstanding_rewards(self, validator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryValidatorOutstandingRewardsRequest(validator_address=validator_address) + response = await self._execute_call(call=self._stub.ValidatorOutstandingRewards, request=request) + + return response + + async def fetch_validator_commission(self, validator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryValidatorCommissionRequest(validator_address=validator_address) + response = await self._execute_call(call=self._stub.ValidatorCommission, request=request) + + return response + + async def fetch_validator_slashes( + self, + validator_address: str, + starting_height: Optional[int] = None, + ending_height: Optional[int] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + pagination_request = None + if pagination is not None: + pagination_request = pagination.create_pagination_request() + request = distribution_query_pb.QueryValidatorSlashesRequest( + validator_address=validator_address, + starting_height=starting_height, + ending_height=ending_height, + pagination=pagination_request, + ) + response = await self._execute_call(call=self._stub.ValidatorSlashes, request=request) + + return response + + async def fetch_delegation_rewards( + self, + delegator_address: str, + validator_address: str, + ) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegationRewardsRequest( + delegator_address=delegator_address, + validator_address=validator_address, + ) + response = await self._execute_call(call=self._stub.DelegationRewards, request=request) + + return response + + async def fetch_delegation_total_rewards( + self, + delegator_address: str, + ) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegationTotalRewardsRequest( + delegator_address=delegator_address, + ) + response = await self._execute_call(call=self._stub.DelegationTotalRewards, request=request) + + return response + + async def fetch_delegator_validators(self, delegator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegatorValidatorsRequest( + delegator_address=delegator_address, + ) + response = await self._execute_call(call=self._stub.DelegatorValidators, request=request) + + return response + + async def fetch_delegator_withdraw_address(self, delegator_address: str) -> Dict[str, Any]: + request = distribution_query_pb.QueryDelegatorWithdrawAddressRequest( + delegator_address=delegator_address, + ) + response = await self._execute_call(call=self._stub.DelegatorWithdrawAddress, request=request) + + return response + + async def fetch_community_pool(self) -> Dict[str, Any]: + request = distribution_query_pb.QueryCommunityPoolRequest() + response = await self._execute_call(call=self._stub.CommunityPool, request=request) + + return response + + async def _execute_call(self, call: Callable, request) -> Dict[str, Any]: + return await self._assistant.execute_call(call=call, request=request) diff --git a/tests/client/chain/grpc/configurable_autz_query_servicer.py b/tests/client/chain/grpc/configurable_authz_query_servicer.py similarity index 100% rename from tests/client/chain/grpc/configurable_autz_query_servicer.py rename to tests/client/chain/grpc/configurable_authz_query_servicer.py diff --git a/tests/client/chain/grpc/configurable_distribution_query_servicer.py b/tests/client/chain/grpc/configurable_distribution_query_servicer.py new file mode 100644 index 00000000..d2e1d7da --- /dev/null +++ b/tests/client/chain/grpc/configurable_distribution_query_servicer.py @@ -0,0 +1,69 @@ +from collections import deque + +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + query_pb2 as distribution_query_pb, + query_pb2_grpc as distribution_query_grpc, +) + + +class ConfigurableDistributionQueryServicer(distribution_query_grpc.QueryServicer): + def __init__(self): + super().__init__() + self.distribution_params = deque() + self.validator_distribution_info_responses = deque() + self.validator_outstanding_rewards_responses = deque() + self.validator_commission_responses = deque() + self.validator_slashes_responses = deque() + self.delegation_rewards_responses = deque() + self.delegation_total_rewards_responses = deque() + self.delegator_validators_responses = deque() + self.delegator_withdraw_address_responses = deque() + self.community_pool_responses = deque() + + async def Params(self, request: distribution_query_pb.QueryParamsRequest, context=None, metadata=None): + return self.distribution_params.pop() + + async def ValidatorDistributionInfo( + self, request: distribution_query_pb.QueryValidatorDistributionInfoRequest, context=None, metadata=None + ): + return self.validator_distribution_info_responses.pop() + + async def ValidatorOutstandingRewards( + self, request: distribution_query_pb.QueryValidatorOutstandingRewardsRequest, context=None, metadata=None + ): + return self.validator_outstanding_rewards_responses.pop() + + async def ValidatorCommission( + self, request: distribution_query_pb.QueryValidatorCommissionRequest, context=None, metadata=None + ): + return self.validator_commission_responses.pop() + + async def ValidatorSlashes( + self, request: distribution_query_pb.QueryValidatorSlashesRequest, context=None, metadata=None + ): + return self.validator_slashes_responses.pop() + + async def DelegationRewards( + self, request: distribution_query_pb.QueryDelegationRewardsRequest, context=None, metadata=None + ): + return self.delegation_rewards_responses.pop() + + async def DelegationTotalRewards( + self, request: distribution_query_pb.QueryDelegationTotalRewardsRequest, context=None, metadata=None + ): + return self.delegation_total_rewards_responses.pop() + + async def DelegatorValidators( + self, request: distribution_query_pb.QueryDelegatorValidatorsRequest, context=None, metadata=None + ): + return self.delegator_validators_responses.pop() + + async def DelegatorWithdrawAddress( + self, request: distribution_query_pb.QueryDelegatorWithdrawAddressRequest, context=None, metadata=None + ): + return self.delegator_withdraw_address_responses.pop() + + async def CommunityPool( + self, request: distribution_query_pb.QueryCommunityPoolRequest, context=None, metadata=None + ): + return self.community_pool_responses.pop() diff --git a/tests/client/chain/grpc/test_chain_grpc_distribution_api.py b/tests/client/chain/grpc/test_chain_grpc_distribution_api.py new file mode 100644 index 00000000..9f8ee9a6 --- /dev/null +++ b/tests/client/chain/grpc/test_chain_grpc_distribution_api.py @@ -0,0 +1,338 @@ +import base64 + +import grpc +import pytest + +from pyinjective.client.chain.grpc.chain_grpc_distribution_api import ChainGrpcDistributionApi +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network +from pyinjective.proto.cosmos.base.query.v1beta1 import pagination_pb2 as pagination_pb +from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as coin_pb +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + distribution_pb2 as distribution_pb, + query_pb2 as distribution_query_pb, +) +from tests.client.chain.grpc.configurable_distribution_query_servicer import ConfigurableDistributionQueryServicer + + +@pytest.fixture +def distribution_servicer(): + return ConfigurableDistributionQueryServicer() + + +class TestChainGrpcAuthApi: + @pytest.mark.asyncio + async def test_fetch_module_params( + self, + distribution_servicer, + ): + params = distribution_pb.Params( + community_tax="0.050000000000000000", + base_proposer_reward="0.060000000000000000", + bonus_proposer_reward="0.070000000000000000", + withdraw_addr_enabled=True, + ) + + distribution_servicer.distribution_params.append(distribution_query_pb.QueryParamsResponse(params=params)) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + module_params = await api.fetch_module_params() + expected_params = { + "params": { + "communityTax": params.community_tax, + "baseProposerReward": params.base_proposer_reward, + "bonusProposerReward": params.bonus_proposer_reward, + "withdrawAddrEnabled": params.withdraw_addr_enabled, + } + } + + assert expected_params == module_params + + @pytest.mark.asyncio + async def test_fetch_validator_distribution_info( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + commission = coin_pb.DecCoin(denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", amount="54497408") + + distribution_servicer.validator_distribution_info_responses.append( + distribution_query_pb.QueryValidatorDistributionInfoResponse( + operator_address=operator, self_bond_rewards=[reward], commission=[commission] + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + validator_info = await api.fetch_validator_distribution_info(validator_address=operator) + expected_info = { + "operatorAddress": operator, + "selfBondRewards": [{"denom": reward.denom, "amount": reward.amount}], + "commission": [{"denom": commission.denom, "amount": commission.amount}], + } + + assert expected_info == validator_info + + @pytest.mark.asyncio + async def test_fetch_validator_outstanding_rewards( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + rewards = distribution_pb.ValidatorOutstandingRewards(rewards=[reward]) + + distribution_servicer.validator_outstanding_rewards_responses.append( + distribution_query_pb.QueryValidatorOutstandingRewardsResponse( + rewards=rewards, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + validator_rewards = await api.fetch_validator_outstanding_rewards(validator_address=operator) + expected_rewards = {"rewards": {"rewards": [{"denom": reward.denom, "amount": reward.amount}]}} + + assert expected_rewards == validator_rewards + + @pytest.mark.asyncio + async def test_fetch_validator_commission( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + first_commission = coin_pb.DecCoin(denom="inj", amount="1000000000") + commission = distribution_pb.ValidatorAccumulatedCommission(commission=[first_commission]) + + distribution_servicer.validator_commission_responses.append( + distribution_query_pb.QueryValidatorCommissionResponse( + commission=commission, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + commission = await api.fetch_validator_commission(validator_address=operator) + expected_commission = { + "commission": {"commission": [{"denom": first_commission.denom, "amount": first_commission.amount}]} + } + + assert expected_commission == commission + + @pytest.mark.asyncio + async def test_fetch_validator_slashes( + self, + distribution_servicer, + ): + operator = "inj1zpy3qf7us3m0pxpqkp72gzjv55t70huyxh7slz" + slash = distribution_pb.ValidatorSlashEvent( + validator_period=1, + fraction="4", + ) + pagination = pagination_pb.PageResponse(total=2) + + distribution_servicer.validator_slashes_responses.append( + distribution_query_pb.QueryValidatorSlashesResponse( + slashes=[slash], + pagination=pagination, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + slashes = await api.fetch_validator_slashes( + validator_address=operator, + starting_height=20, + ending_height=100, + pagination=PaginationOption( + skip=0, + limit=100, + ), + ) + expected_slashes = { + "slashes": [ + { + "validatorPeriod": str(slash.validator_period), + "fraction": slash.fraction, + } + ], + "pagination": {"nextKey": base64.b64encode(pagination.next_key).decode(), "total": str(pagination.total)}, + } + + assert slashes == expected_slashes + + @pytest.mark.asyncio + async def test_fetch_delegation_rewards( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + validator = "injvaloper16gdnrnl224ylje5z9vd0vn0msym7p58f00qauj" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + + distribution_servicer.delegation_rewards_responses.append( + distribution_query_pb.QueryDelegationRewardsResponse( + rewards=[reward], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + rewards = await api.fetch_delegation_rewards( + delegator_address=delegator, + validator_address=validator, + ) + expected_rewards = {"rewards": [{"denom": reward.denom, "amount": reward.amount}]} + + assert rewards == expected_rewards + + @pytest.mark.asyncio + async def test_fetch_delegation_total_rewards( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + validator = "injvaloper16gdnrnl224ylje5z9vd0vn0msym7p58f00qauj" + reward = coin_pb.DecCoin(denom="inj", amount="1000000000") + delegation_delegator_reward = distribution_pb.DelegationDelegatorReward( + validator_address=validator, + reward=[reward], + ) + total = coin_pb.DecCoin(denom="inj", amount="2000000000") + + distribution_servicer.delegation_total_rewards_responses.append( + distribution_query_pb.QueryDelegationTotalRewardsResponse( + rewards=[delegation_delegator_reward], + total=[total], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + rewards = await api.fetch_delegation_total_rewards( + delegator_address=delegator, + ) + expected_rewards = { + "rewards": [ + { + "validatorAddress": validator, + "reward": [{"denom": reward.denom, "amount": reward.amount}], + } + ], + "total": [{"denom": total.denom, "amount": total.amount}], + } + + assert rewards == expected_rewards + + @pytest.mark.asyncio + async def test_fetch_delegator_validators( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + validator = "injvaloper16gdnrnl224ylje5z9vd0vn0msym7p58f00qauj" + + distribution_servicer.delegator_validators_responses.append( + distribution_query_pb.QueryDelegatorValidatorsResponse( + validators=[validator], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + validators = await api.fetch_delegator_validators( + delegator_address=delegator, + ) + expected_validators = { + "validators": [validator], + } + + assert validators == expected_validators + + @pytest.mark.asyncio + async def test_fetch_delegator_withdraw_address( + self, + distribution_servicer, + ): + delegator = "inj1cml96vmptgw99syqrrz8az79xer2pcgp0a885r" + + distribution_servicer.delegator_withdraw_address_responses.append( + distribution_query_pb.QueryDelegatorWithdrawAddressResponse( + withdraw_address=delegator, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + withdraw_address = await api.fetch_delegator_withdraw_address( + delegator_address=delegator, + ) + expected_withdraw_address = { + "withdrawAddress": delegator, + } + + assert withdraw_address == expected_withdraw_address + + @pytest.mark.asyncio + async def test_fetch_community_pool( + self, + distribution_servicer, + ): + coin = coin_pb.DecCoin(denom="inj", amount="1000000000") + distribution_servicer.community_pool_responses.append( + distribution_query_pb.QueryCommunityPoolResponse( + pool=[coin], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcDistributionApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = distribution_servicer + + community_pool = await api.fetch_community_pool() + expected_community_pool = {"pool": [{"denom": coin.denom, "amount": coin.amount}]} + + assert community_pool == expected_community_pool + + async def _dummy_metadata_provider(self): + return None From d976f697d8cbaf9ef2822a58a2f742b8c2a6c117 Mon Sep 17 00:00:00 2001 From: abel Date: Fri, 9 Feb 2024 00:16:59 -0300 Subject: [PATCH 33/44] (fix) Fix error due to incomplete rename --- tests/client/chain/grpc/test_chain_grpc_authz_api.py | 2 +- tests/test_async_client_deprecation_warnings.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/client/chain/grpc/test_chain_grpc_authz_api.py b/tests/client/chain/grpc/test_chain_grpc_authz_api.py index e097ff66..9d1d5586 100644 --- a/tests/client/chain/grpc/test_chain_grpc_authz_api.py +++ b/tests/client/chain/grpc/test_chain_grpc_authz_api.py @@ -7,7 +7,7 @@ from pyinjective.core.network import Network from pyinjective.proto.cosmos.authz.v1beta1 import authz_pb2, query_pb2 as authz_query from pyinjective.proto.cosmos.base.query.v1beta1 import pagination_pb2 as pagination_pb -from tests.client.chain.grpc.configurable_autz_query_servicer import ConfigurableAuthZQueryServicer +from tests.client.chain.grpc.configurable_authz_query_servicer import ConfigurableAuthZQueryServicer @pytest.fixture diff --git a/tests/test_async_client_deprecation_warnings.py b/tests/test_async_client_deprecation_warnings.py index dae2d807..1df77fe8 100644 --- a/tests/test_async_client_deprecation_warnings.py +++ b/tests/test_async_client_deprecation_warnings.py @@ -21,7 +21,7 @@ from pyinjective.proto.injective.stream.v1beta1 import query_pb2 as chain_stream_pb from pyinjective.proto.injective.types.v1beta1 import account_pb2 as account_pb from tests.client.chain.grpc.configurable_auth_query_servicer import ConfigurableAuthQueryServicer -from tests.client.chain.grpc.configurable_autz_query_servicer import ConfigurableAuthZQueryServicer +from tests.client.chain.grpc.configurable_authz_query_servicer import ConfigurableAuthZQueryServicer from tests.client.chain.grpc.configurable_bank_query_servicer import ConfigurableBankQueryServicer from tests.client.chain.stream_grpc.configurable_chain_stream_query_servicer import ConfigurableChainStreamQueryServicer from tests.client.indexer.configurable_account_query_servicer import ConfigurableAccountQueryServicer From 873e8c7daea74b500149101198c518407609b365 Mon Sep 17 00:00:00 2001 From: abel Date: Mon, 12 Feb 2024 15:44:17 -0300 Subject: [PATCH 34/44] (feat) Added support in Composer to create all missing messages from the `distribution` module. Marked as deprecated old functions not following Python naming standards and created the replacements for them (with the correct name following standards) --- examples/chain_client/0_LocalOrderHash.py | 6 +- .../13_MsgIncreasePositionMargin.py | 2 +- examples/chain_client/15_MsgWithdraw.py | 2 +- .../chain_client/16_MsgSubaccountTransfer.py | 2 +- .../chain_client/17_MsgBatchUpdateOrders.py | 2 +- examples/chain_client/18_MsgBid.py | 2 +- examples/chain_client/19_MsgGrant.py | 2 +- examples/chain_client/1_MsgSend.py | 2 +- examples/chain_client/20_MsgExec.py | 2 +- examples/chain_client/21_MsgRevoke.py | 2 +- examples/chain_client/22_MsgSendToEth.py | 2 +- .../chain_client/23_MsgRelayPriceFeedPrice.py | 2 +- examples/chain_client/24_MsgRewardsOptOut.py | 2 +- examples/chain_client/25_MsgDelegate.py | 2 +- .../26_MsgWithdrawDelegatorReward.py | 81 ----------- examples/chain_client/2_MsgDeposit.py | 2 +- examples/chain_client/30_ExternalTransfer.py | 2 +- .../31_MsgCreateBinaryOptionsLimitOrder.py | 2 +- .../32_MsgCreateBinaryOptionsMarketOrder.py | 2 +- .../33_MsgCancelBinaryOptionsOrder.py | 2 +- .../34_MsgAdminUpdateBinaryOptionsMarket.py | 2 +- .../35_MsgInstantBinaryOptionsMarketLaunch.py | 2 +- .../chain_client/36_MsgRelayProviderPrices.py | 2 +- .../chain_client/3_MsgCreateSpotLimitOrder.py | 2 +- .../chain_client/40_MsgExecuteContract.py | 8 +- .../chain_client/41_MsgCreateInsuranceFund.py | 2 +- examples/chain_client/42_MsgUnderwrite.py | 2 +- .../chain_client/43_MsgRequestRedemption.py | 2 +- ...8_WithdrawValidatorCommissionAndRewards.py | 86 ------------ .../4_MsgCreateSpotMarketOrder.py | 2 +- examples/chain_client/5_MsgCancelSpotOrder.py | 2 +- .../6_MsgCreateDerivativeLimitOrder.py | 2 +- examples/chain_client/72_MsgMint.py | 2 +- examples/chain_client/73_MsgBurn.py | 2 +- .../76_MsgExecuteContractCompat.py | 2 +- .../chain_client/77_MsgLiquidatePosition.py | 2 +- .../7_MsgCreateDerivativeMarketOrder.py | 2 +- .../8_MsgCancelDerivativeOrder.py | 2 +- .../distribution/10_SetWithdrawAddress.py | 46 ++++++ .../11_WithdrawDelegatorReward.py | 47 +++++++ .../12_WithdrawValidatorCommission.py | 45 ++++++ .../distribution/13_FundCommunityPool.py | 47 +++++++ pyinjective/composer.py | 132 +++++++++++++----- pyinjective/core/broadcaster.py | 4 +- tests/test_composer.py | 4 +- 45 files changed, 325 insertions(+), 249 deletions(-) delete mode 100644 examples/chain_client/26_MsgWithdrawDelegatorReward.py delete mode 100644 examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py create mode 100644 examples/chain_client/distribution/10_SetWithdrawAddress.py create mode 100644 examples/chain_client/distribution/11_WithdrawDelegatorReward.py create mode 100644 examples/chain_client/distribution/12_WithdrawValidatorCommission.py create mode 100644 examples/chain_client/distribution/13_FundCommunityPool.py diff --git a/examples/chain_client/0_LocalOrderHash.py b/examples/chain_client/0_LocalOrderHash.py index a25398c6..770ad5bf 100644 --- a/examples/chain_client/0_LocalOrderHash.py +++ b/examples/chain_client/0_LocalOrderHash.py @@ -113,7 +113,7 @@ async def main() -> None: gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) @@ -150,7 +150,7 @@ async def main() -> None: gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) @@ -240,7 +240,7 @@ async def main() -> None: gas_limit = base_gas + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/13_MsgIncreasePositionMargin.py b/examples/chain_client/13_MsgIncreasePositionMargin.py index f54910f8..775a41e5 100644 --- a/examples/chain_client/13_MsgIncreasePositionMargin.py +++ b/examples/chain_client/13_MsgIncreasePositionMargin.py @@ -66,7 +66,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/15_MsgWithdraw.py b/examples/chain_client/15_MsgWithdraw.py index a8c267d8..b198c0aa 100644 --- a/examples/chain_client/15_MsgWithdraw.py +++ b/examples/chain_client/15_MsgWithdraw.py @@ -57,7 +57,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/16_MsgSubaccountTransfer.py b/examples/chain_client/16_MsgSubaccountTransfer.py index d87eb0ed..b68717b2 100644 --- a/examples/chain_client/16_MsgSubaccountTransfer.py +++ b/examples/chain_client/16_MsgSubaccountTransfer.py @@ -64,7 +64,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/17_MsgBatchUpdateOrders.py b/examples/chain_client/17_MsgBatchUpdateOrders.py index 557ffe46..9efdc0a0 100644 --- a/examples/chain_client/17_MsgBatchUpdateOrders.py +++ b/examples/chain_client/17_MsgBatchUpdateOrders.py @@ -153,7 +153,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/18_MsgBid.py b/examples/chain_client/18_MsgBid.py index 8e5f8d5e..1efaa3e3 100644 --- a/examples/chain_client/18_MsgBid.py +++ b/examples/chain_client/18_MsgBid.py @@ -56,7 +56,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/19_MsgGrant.py b/examples/chain_client/19_MsgGrant.py index 32a82fe7..111a050c 100644 --- a/examples/chain_client/19_MsgGrant.py +++ b/examples/chain_client/19_MsgGrant.py @@ -76,7 +76,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/1_MsgSend.py b/examples/chain_client/1_MsgSend.py index 6389c8be..1d926898 100644 --- a/examples/chain_client/1_MsgSend.py +++ b/examples/chain_client/1_MsgSend.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/20_MsgExec.py b/examples/chain_client/20_MsgExec.py index d5ff2dc5..1203ff90 100644 --- a/examples/chain_client/20_MsgExec.py +++ b/examples/chain_client/20_MsgExec.py @@ -83,7 +83,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/21_MsgRevoke.py b/examples/chain_client/21_MsgRevoke.py index 82663004..91bb192d 100644 --- a/examples/chain_client/21_MsgRevoke.py +++ b/examples/chain_client/21_MsgRevoke.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/22_MsgSendToEth.py b/examples/chain_client/22_MsgSendToEth.py index 59bdc877..06e2d78c 100644 --- a/examples/chain_client/22_MsgSendToEth.py +++ b/examples/chain_client/22_MsgSendToEth.py @@ -70,7 +70,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/23_MsgRelayPriceFeedPrice.py b/examples/chain_client/23_MsgRelayPriceFeedPrice.py index cc7055c9..b59b34a3 100644 --- a/examples/chain_client/23_MsgRelayPriceFeedPrice.py +++ b/examples/chain_client/23_MsgRelayPriceFeedPrice.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/24_MsgRewardsOptOut.py b/examples/chain_client/24_MsgRewardsOptOut.py index 5fa2f429..8beaa1f4 100644 --- a/examples/chain_client/24_MsgRewardsOptOut.py +++ b/examples/chain_client/24_MsgRewardsOptOut.py @@ -56,7 +56,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/25_MsgDelegate.py b/examples/chain_client/25_MsgDelegate.py index ada14ce0..e32f6691 100644 --- a/examples/chain_client/25_MsgDelegate.py +++ b/examples/chain_client/25_MsgDelegate.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/26_MsgWithdrawDelegatorReward.py b/examples/chain_client/26_MsgWithdrawDelegatorReward.py deleted file mode 100644 index f9370c23..00000000 --- a/examples/chain_client/26_MsgWithdrawDelegatorReward.py +++ /dev/null @@ -1,81 +0,0 @@ -import asyncio -import os - -import dotenv -from grpc import RpcError - -from pyinjective.async_client import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE -from pyinjective.core.network import Network -from pyinjective.transaction import Transaction -from pyinjective.wallet import PrivateKey - - -async def main() -> None: - dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") - - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - composer = await client.composer() - await client.sync_timeout_height() - - # load account - priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - # prepare tx msg - validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" - - msg = composer.MsgWithdrawDelegatorReward( - delegator_address=address.to_acc_bech32(), validator_address=validator_address - ) - - # build sim tx - tx = ( - Transaction() - .with_messages(msg) - .with_sequence(client.get_sequence()) - .with_account_num(client.get_number()) - .with_chain_id(network.chain_id) - ) - sim_sign_doc = tx.get_sign_doc(pub_key) - sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) - sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key) - - # simulate tx - try: - sim_res = await client.simulate(sim_tx_raw_bytes) - except RpcError as ex: - print(ex) - return - - # build tx - gas_price = GAS_PRICE - gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation - gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") - fee = [ - composer.Coin( - amount=gas_price * gas_limit, - denom=network.fee_denom, - ) - ] - tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height) - sign_doc = tx.get_sign_doc(pub_key) - sig = priv_key.sign(sign_doc.SerializeToString()) - tx_raw_bytes = tx.get_tx_data(sig, pub_key) - - # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode - res = await client.broadcast_tx_sync_mode(tx_raw_bytes) - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/2_MsgDeposit.py b/examples/chain_client/2_MsgDeposit.py index 80587c55..80b9f652 100644 --- a/examples/chain_client/2_MsgDeposit.py +++ b/examples/chain_client/2_MsgDeposit.py @@ -57,7 +57,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/30_ExternalTransfer.py b/examples/chain_client/30_ExternalTransfer.py index 7ab6e0f2..3200be34 100644 --- a/examples/chain_client/30_ExternalTransfer.py +++ b/examples/chain_client/30_ExternalTransfer.py @@ -64,7 +64,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py index 57f5537b..2a58e173 100644 --- a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py +++ b/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py @@ -81,7 +81,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py index 473e8e53..2d07658f 100644 --- a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py +++ b/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py @@ -75,7 +75,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py index 15159f00..82107f3c 100644 --- a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py +++ b/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py @@ -66,7 +66,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py index 55c308be..0f39dcdb 100644 --- a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py +++ b/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py @@ -74,7 +74,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py index 7e865320..7b8a6567 100644 --- a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py +++ b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py @@ -76,7 +76,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/36_MsgRelayProviderPrices.py b/examples/chain_client/36_MsgRelayProviderPrices.py index 4ee5fc3f..1e3b9c8f 100644 --- a/examples/chain_client/36_MsgRelayProviderPrices.py +++ b/examples/chain_client/36_MsgRelayProviderPrices.py @@ -66,7 +66,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/3_MsgCreateSpotLimitOrder.py index dd06672a..d3ca5f16 100644 --- a/examples/chain_client/3_MsgCreateSpotLimitOrder.py +++ b/examples/chain_client/3_MsgCreateSpotLimitOrder.py @@ -77,7 +77,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/40_MsgExecuteContract.py b/examples/chain_client/40_MsgExecuteContract.py index f2d1b719..d18c6398 100644 --- a/examples/chain_client/40_MsgExecuteContract.py +++ b/examples/chain_client/40_MsgExecuteContract.py @@ -33,12 +33,12 @@ async def main() -> None: # prepare tx msg # NOTE: COIN MUST BE SORTED IN ALPHABETICAL ORDER BY DENOMS funds = [ - composer.Coin( + composer.coin( amount=69, denom="factory/inj1hdvy6tl89llqy3ze8lv6mz5qh66sx9enn0jxg6/inj12ngevx045zpvacus9s6anr258gkwpmthnz80e9", ), - composer.Coin(amount=420, denom="peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7"), - composer.Coin(amount=1, denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"), + composer.coin(amount=420, denom="peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7"), + composer.coin(amount=1, denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"), ] msg = composer.MsgExecuteContract( sender=address.to_acc_bech32(), @@ -71,7 +71,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/41_MsgCreateInsuranceFund.py b/examples/chain_client/41_MsgCreateInsuranceFund.py index 74f94bfa..99c10fc0 100644 --- a/examples/chain_client/41_MsgCreateInsuranceFund.py +++ b/examples/chain_client/41_MsgCreateInsuranceFund.py @@ -65,7 +65,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/42_MsgUnderwrite.py b/examples/chain_client/42_MsgUnderwrite.py index 20c65a64..16b75e70 100644 --- a/examples/chain_client/42_MsgUnderwrite.py +++ b/examples/chain_client/42_MsgUnderwrite.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/43_MsgRequestRedemption.py b/examples/chain_client/43_MsgRequestRedemption.py index 4413044b..ecc2793c 100644 --- a/examples/chain_client/43_MsgRequestRedemption.py +++ b/examples/chain_client/43_MsgRequestRedemption.py @@ -61,7 +61,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py b/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py deleted file mode 100644 index 2f67f6c4..00000000 --- a/examples/chain_client/48_WithdrawValidatorCommissionAndRewards.py +++ /dev/null @@ -1,86 +0,0 @@ -import asyncio -import os - -import dotenv -from grpc import RpcError - -from pyinjective.async_client import AsyncClient -from pyinjective.composer import Composer as ProtoMsgComposer -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE -from pyinjective.core.network import Network -from pyinjective.transaction import Transaction -from pyinjective.wallet import PrivateKey - - -async def main() -> None: - dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") - - """For a validator to withdraw his rewards & commissions simultaneously""" - # select network: local, testnet, mainnet - network = Network.testnet() - composer = ProtoMsgComposer(network=network.string()) - - # initialize grpc client - client = AsyncClient(network, insecure=False) - await client.sync_timeout_height() - - # load account - # private key is that from the validator's wallet - priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - # prepare tx msg - validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" - - msg0 = composer.MsgWithdrawDelegatorReward( - delegator_address=address.to_acc_bech32(), validator_address=validator_address - ) - - msg1 = composer.MsgWithdrawValidatorCommission(validator_address=validator_address) - - # build sim tx - tx = ( - Transaction() - .with_messages(msg0, msg1) - .with_sequence(client.get_sequence()) - .with_account_num(client.get_number()) - .with_chain_id(network.chain_id) - ) - sim_sign_doc = tx.get_sign_doc(pub_key) - sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) - sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key) - - # simulate tx - try: - sim_res = await client.simulate(sim_tx_raw_bytes) - except RpcError as ex: - print(ex) - return - - # build tx - gas_price = GAS_PRICE - gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation - gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") - fee = [ - composer.Coin( - amount=gas_price * gas_limit, - denom=network.fee_denom, - ) - ] - tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height) - sign_doc = tx.get_sign_doc(pub_key) - sig = priv_key.sign(sign_doc.SerializeToString()) - tx_raw_bytes = tx.get_tx_data(sig, pub_key) - - # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode - res = await client.broadcast_tx_sync_mode(tx_raw_bytes) - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/4_MsgCreateSpotMarketOrder.py index 06a42a96..5229632f 100644 --- a/examples/chain_client/4_MsgCreateSpotMarketOrder.py +++ b/examples/chain_client/4_MsgCreateSpotMarketOrder.py @@ -75,7 +75,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/5_MsgCancelSpotOrder.py b/examples/chain_client/5_MsgCancelSpotOrder.py index 63167309..970b2190 100644 --- a/examples/chain_client/5_MsgCancelSpotOrder.py +++ b/examples/chain_client/5_MsgCancelSpotOrder.py @@ -63,7 +63,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py index e46f1acb..41a19307 100644 --- a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py @@ -77,7 +77,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/72_MsgMint.py b/examples/chain_client/72_MsgMint.py index d38449be..b6617431 100644 --- a/examples/chain_client/72_MsgMint.py +++ b/examples/chain_client/72_MsgMint.py @@ -26,7 +26,7 @@ async def main() -> None: pub_key = priv_key.to_public_key() address = pub_key.to_address() - amount = composer.Coin(amount=1_000_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") + amount = composer.coin(amount=1_000_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") message = composer.msg_mint( sender=address.to_acc_bech32(), diff --git a/examples/chain_client/73_MsgBurn.py b/examples/chain_client/73_MsgBurn.py index 441f4ee8..c4aa013a 100644 --- a/examples/chain_client/73_MsgBurn.py +++ b/examples/chain_client/73_MsgBurn.py @@ -26,7 +26,7 @@ async def main() -> None: pub_key = priv_key.to_public_key() address = pub_key.to_address() - amount = composer.Coin(amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") + amount = composer.coin(amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test") message = composer.msg_burn( sender=address.to_acc_bech32(), diff --git a/examples/chain_client/76_MsgExecuteContractCompat.py b/examples/chain_client/76_MsgExecuteContractCompat.py index 892c125f..a195c7c4 100644 --- a/examples/chain_client/76_MsgExecuteContractCompat.py +++ b/examples/chain_client/76_MsgExecuteContractCompat.py @@ -68,7 +68,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/77_MsgLiquidatePosition.py b/examples/chain_client/77_MsgLiquidatePosition.py index 6dcbacfb..d80ba385 100644 --- a/examples/chain_client/77_MsgLiquidatePosition.py +++ b/examples/chain_client/77_MsgLiquidatePosition.py @@ -83,7 +83,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py index e7e06c62..37b305ed 100644 --- a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py +++ b/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py @@ -76,7 +76,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/8_MsgCancelDerivativeOrder.py b/examples/chain_client/8_MsgCancelDerivativeOrder.py index 6a59167a..43180b1f 100644 --- a/examples/chain_client/8_MsgCancelDerivativeOrder.py +++ b/examples/chain_client/8_MsgCancelDerivativeOrder.py @@ -63,7 +63,7 @@ async def main() -> None: gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") fee = [ - composer.Coin( + composer.coin( amount=gas_price * gas_limit, denom=network.fee_denom, ) diff --git a/examples/chain_client/distribution/10_SetWithdrawAddress.py b/examples/chain_client/distribution/10_SetWithdrawAddress.py new file mode 100644 index 00000000..b317a998 --- /dev/null +++ b/examples/chain_client/distribution/10_SetWithdrawAddress.py @@ -0,0 +1,46 @@ +import asyncio +import os + +import dotenv + +from pyinjective import AsyncClient, PrivateKey +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + withdraw_address = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + + message = composer.msg_set_withdraw_address( + delegator_address=address.to_acc_bech32(), + withdraw_address=withdraw_address, + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/11_WithdrawDelegatorReward.py b/examples/chain_client/distribution/11_WithdrawDelegatorReward.py new file mode 100644 index 00000000..02facdc7 --- /dev/null +++ b/examples/chain_client/distribution/11_WithdrawDelegatorReward.py @@ -0,0 +1,47 @@ +import asyncio +import os + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" + + message = composer.msg_withdraw_delegator_reward( + delegator_address=address.to_acc_bech32(), validator_address=validator_address + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/12_WithdrawValidatorCommission.py b/examples/chain_client/distribution/12_WithdrawValidatorCommission.py new file mode 100644 index 00000000..cd351d1f --- /dev/null +++ b/examples/chain_client/distribution/12_WithdrawValidatorCommission.py @@ -0,0 +1,45 @@ +import asyncio +import os + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + validator_address = "injvaloper1ultw9r29l8nxy5u6thcgusjn95vsy2caw722q5" + + message = composer.msg_withdraw_validator_commission(validator_address=validator_address) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/distribution/13_FundCommunityPool.py b/examples/chain_client/distribution/13_FundCommunityPool.py new file mode 100644 index 00000000..c60475c8 --- /dev/null +++ b/examples/chain_client/distribution/13_FundCommunityPool.py @@ -0,0 +1,47 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective import AsyncClient, PrivateKey +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + client = AsyncClient(network) + composer = await client.composer() + + message_broadcaster = MsgBroadcasterWithPk.new_without_simulation( + network=network, + private_key=configured_private_key, + client=client, + composer=composer, + ) + + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + amount = composer.create_coin_amount(amount=Decimal("0.1"), token_name="INJ") + + message = composer.msg_fund_community_pool( + amounts=[amount], + depositor=address.to_acc_bech32(), + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/pyinjective/composer.py b/pyinjective/composer.py index 720920d1..df353d6b 100644 --- a/pyinjective/composer.py +++ b/pyinjective/composer.py @@ -3,6 +3,7 @@ from decimal import Decimal from time import time from typing import Any, Dict, List, Optional +from warnings import warn from google.protobuf import any_pb2, json_format, timestamp_pb2 @@ -13,7 +14,10 @@ from pyinjective.proto.cosmos.authz.v1beta1 import authz_pb2 as cosmos_authz_pb, tx_pb2 as cosmos_authz_tx_pb from pyinjective.proto.cosmos.bank.v1beta1 import bank_pb2 as bank_pb, tx_pb2 as cosmos_bank_tx_pb from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as cosmos_dot_base_dot_v1beta1_dot_coin__pb2 -from pyinjective.proto.cosmos.distribution.v1beta1 import tx_pb2 as cosmos_distribution_tx_pb +from pyinjective.proto.cosmos.distribution.v1beta1 import ( + distribution_pb2 as cosmos_distribution_pb2, + tx_pb2 as cosmos_distribution_tx_pb, +) from pyinjective.proto.cosmos.gov.v1beta1 import tx_pb2 as cosmos_gov_tx_pb from pyinjective.proto.cosmos.staking.v1beta1 import tx_pb2 as cosmos_staking_tx_pb from pyinjective.proto.cosmwasm.wasm.v1 import tx_pb2 as wasm_tx_pb @@ -129,8 +133,27 @@ def __init__( self.tokens = tokens def Coin(self, amount: int, denom: str): + """ + This method is deprecated and will be removed soon. Please use `coin` instead + """ + warn("This method is deprecated. Use coin instead", DeprecationWarning, stacklevel=2) return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=str(amount), denom=denom) + def coin(self, amount: int, denom: str): + """ + This method create an instance of Coin gRPC type, considering the amount is already expressed in chain format + """ + formatted_amount_string = str(int(amount)) + return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=formatted_amount_string, denom=denom) + + def create_coin_amount(self, amount: Decimal, token_name: str): + """ + This method create an instance of Coin gRPC type, considering the amount is already expressed in chain format + """ + token = self.tokens[token_name] + chain_amount = token.chain_formatted_value(human_readable_value=amount) + return self.coin(amount=int(chain_amount), denom=token.denom) + def get_order_mask(self, **kwargs): order_mask = 0 @@ -331,13 +354,12 @@ def BinaryOptionsOrder( ) def MsgSend(self, from_address: str, to_address: str, amount: float, denom: str): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return cosmos_bank_tx_pb.MsgSend( from_address=from_address, to_address=to_address, - amount=[self.Coin(amount=int(be_amount), denom=token.denom)], + amount=[coin], ) def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): @@ -350,13 +372,12 @@ def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): ) def MsgDeposit(self, sender: str, subaccount_id: str, amount: float, denom: str): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgDeposit( sender=sender, subaccount_id=subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=coin, ) def MsgCreateSpotLimitOrder( @@ -709,24 +730,22 @@ def MsgSubaccountTransfer( amount: int, denom: str, ): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgSubaccountTransfer( sender=sender, source_subaccount_id=source_subaccount_id, destination_subaccount_id=destination_subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=be_amount, ) def MsgWithdraw(self, sender: str, subaccount_id: str, amount: float, denom: str): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgWithdraw( sender=sender, subaccount_id=subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=be_amount, ) def MsgExternalTransfer( @@ -737,14 +756,13 @@ def MsgExternalTransfer( amount: int, denom: str, ): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgExternalTransfer( sender=sender, source_subaccount_id=source_subaccount_id, destination_subaccount_id=destination_subaccount_id, - amount=self.Coin(amount=int(be_amount), denom=token.denom), + amount=coin, ) def MsgBid(self, sender: str, bid_amount: float, round: float): @@ -753,7 +771,7 @@ def MsgBid(self, sender: str, bid_amount: float, round: float): return injective_auction_tx_pb.MsgBid( sender=sender, round=round, - bid_amount=self.Coin(amount=int(be_amount), denom=INJ_DENOM), + bid_amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), ) def MsgGrantGeneric(self, granter: str, grantee: str, msg_type: str, expire_in: int): @@ -851,15 +869,14 @@ def MsgRelayPriceFeedPrice(self, sender: list, base: list, quote: list, price: l return injective_oracle_tx_pb.MsgRelayPriceFeedPrice(sender=sender, base=base, quote=quote, price=price) def MsgSendToEth(self, denom: str, sender: str, eth_dest: str, amount: float, bridge_fee: float): - token = self.tokens[denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) - be_bridge_fee = token.chain_formatted_value(human_readable_value=Decimal(str(bridge_fee))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + be_bridge_fee = self.create_coin_amount(amount=Decimal(str(bridge_fee)), token_name=denom) return injective_peggy_tx_pb.MsgSendToEth( sender=sender, eth_dest=eth_dest, - amount=self.Coin(amount=int(be_amount), denom=token.denom), - bridge_fee=self.Coin(amount=int(be_bridge_fee), denom=token.denom), + amount=be_amount, + bridge_fee=be_bridge_fee, ) def MsgDelegate(self, delegator_address: str, validator_address: str, amount: float): @@ -868,7 +885,7 @@ def MsgDelegate(self, delegator_address: str, validator_address: str, amount: fl return cosmos_staking_tx_pb.MsgDelegate( delegator_address=delegator_address, validator_address=validator_address, - amount=self.Coin(amount=int(be_amount), denom=INJ_DENOM), + amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), ) def MsgCreateInsuranceFund( @@ -883,7 +900,7 @@ def MsgCreateInsuranceFund( initial_deposit: int, ): token = self.tokens[quote_denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(initial_deposit))) + deposit = self.create_coin_amount(Decimal(str(initial_deposit)), quote_denom) return injective_insurance_tx_pb.MsgCreateInsuranceFund( sender=sender, @@ -893,7 +910,7 @@ def MsgCreateInsuranceFund( oracle_quote=oracle_quote, oracle_type=oracle_type, expiry=expiry, - initial_deposit=self.Coin(amount=int(be_amount), denom=token.denom), + initial_deposit=deposit, ) def MsgUnderwrite( @@ -903,13 +920,12 @@ def MsgUnderwrite( quote_denom: str, amount: int, ): - token = self.tokens[quote_denom] - be_amount = token.chain_formatted_value(human_readable_value=Decimal(str(amount))) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=quote_denom) return injective_insurance_tx_pb.MsgUnderwrite( sender=sender, market_id=market_id, - deposit=self.Coin(amount=int(be_amount), denom=token.denom), + deposit=be_amount, ) def MsgRequestRedemption( @@ -922,17 +938,9 @@ def MsgRequestRedemption( return injective_insurance_tx_pb.MsgRequestRedemption( sender=sender, market_id=market_id, - amount=self.Coin(amount=amount, denom=share_denom), + amount=self.coin(amount=amount, denom=share_denom), ) - def MsgWithdrawDelegatorReward(self, delegator_address: str, validator_address: str): - return cosmos_distribution_tx_pb.MsgWithdrawDelegatorReward( - delegator_address=delegator_address, validator_address=validator_address - ) - - def MsgWithdrawValidatorCommission(self, validator_address: str): - return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) - def MsgVote( self, proposal_id: str, @@ -1101,6 +1109,56 @@ def chain_stream_oracle_price_filter( symbols = symbols or ["*"] return chain_stream_query.OraclePriceFilter(symbol=symbols) + # ------------------------------------------------ + # Distribution module's messages + + def msg_set_withdraw_address(self, delegator_address: str, withdraw_address: str): + return cosmos_distribution_tx_pb.MsgSetWithdrawAddress( + delegator_address=delegator_address, withdraw_address=withdraw_address + ) + + # Deprecated + def MsgWithdrawDelegatorReward(self, delegator_address: str, validator_address: str): + """ + This method is deprecated and will be removed soon. Please use `msg_withdraw_delegator_reward` instead + """ + warn("This method is deprecated. Use msg_withdraw_delegator_reward instead", DeprecationWarning, stacklevel=2) + return cosmos_distribution_tx_pb.MsgWithdrawDelegatorReward( + delegator_address=delegator_address, validator_address=validator_address + ) + + def msg_withdraw_delegator_reward(self, delegator_address: str, validator_address: str): + return cosmos_distribution_tx_pb.MsgWithdrawDelegatorReward( + delegator_address=delegator_address, validator_address=validator_address + ) + + def MsgWithdrawValidatorCommission(self, validator_address: str): + """ + This method is deprecated and will be removed soon. Please use `msg_withdraw_validator_commission` instead + """ + warn( + "This method is deprecated. Use msg_withdraw_validator_commission instead", DeprecationWarning, stacklevel=2 + ) + return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) + + def msg_withdraw_validator_commission(self, validator_address: str): + return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) + + def msg_fund_community_pool(self, amounts: List[cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin], depositor: str): + return cosmos_distribution_tx_pb.MsgFundCommunityPool(amount=amounts, depositor=depositor) + + def msg_update_distribution_params(self, authority: str, community_tax: str, withdraw_address_enabled: bool): + params = cosmos_distribution_pb2.Params( + community_tax=community_tax, + withdraw_addr_enabled=withdraw_address_enabled, + ) + return cosmos_distribution_tx_pb.MsgUpdateParams(authority=authority, params=params) + + def msg_community_pool_spend( + self, authority: str, recipient: str, amount: List[cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin] + ): + return cosmos_distribution_tx_pb.MsgCommunityPoolSpend(authority=authority, recipient=recipient, amount=amount) + # data field format: [request-msg-header][raw-byte-msg-response] # you need to figure out this magic prefix number to trim request-msg-header off the data # this method handles only exchange responses diff --git a/pyinjective/core/broadcaster.py b/pyinjective/core/broadcaster.py index 22df562b..f279baea 100644 --- a/pyinjective/core/broadcaster.py +++ b/pyinjective/core/broadcaster.py @@ -264,7 +264,7 @@ async def configure_gas_fee_for_transaction( gas_limit = math.ceil(Decimal(str(sim_res["gasInfo"]["gasUsed"])) * self._gas_limit_adjustment_multiplier) fee = [ - self._composer.Coin( + self._composer.coin( amount=self._gas_price * gas_limit, denom=self._client.network.fee_denom, ) @@ -292,7 +292,7 @@ async def configure_gas_fee_for_transaction( transaction_gas_limit = messages_gas_limit + self.TRANSACTION_GAS_LIMIT fee = [ - self._composer.Coin( + self._composer.coin( amount=math.ceil(self._gas_price * transaction_gas_limit), denom=self._client.network.fee_denom, ) diff --git a/tests/test_composer.py b/tests/test_composer.py index 4f756c79..a0cca2ab 100644 --- a/tests/test_composer.py +++ b/tests/test_composer.py @@ -282,7 +282,7 @@ def test_msg_create_denom(self, basic_composer: Composer): def test_msg_mint(self, basic_composer: Composer): sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" - amount = basic_composer.Coin( + amount = basic_composer.coin( amount=1_000_000, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test", ) @@ -297,7 +297,7 @@ def test_msg_mint(self, basic_composer: Composer): def test_msg_burn(self, basic_composer: Composer): sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" - amount = basic_composer.Coin( + amount = basic_composer.coin( amount=100, denom="factory/inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r/inj_test", ) From 364f022c251692b12871be5d5a1f1542267e19ca Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 20 Feb 2024 12:52:10 -0300 Subject: [PATCH 35/44] (feat) Added support for all chain exchange module queries. Included new example scripts for all the queries and unit tests. --- ...drawAddress.py => 1_SetWithdrawAddress.py} | 0 ...Reward.py => 2_WithdrawDelegatorReward.py} | 0 ...on.py => 3_WithdrawValidatorCommission.py} | 0 ...ommunityPool.py => 4_FundCommunityPool.py} | 0 .../1_ValidatorDistributionInfo.py | 0 .../2_ValidatorOutstandingRewards.py | 0 .../{ => query}/3_ValidatorCommission.py | 0 .../{ => query}/4_ValidatorSlashes.py | 0 .../{ => query}/5_DelegationRewards.py | 0 .../{ => query}/6_DelegationTotalRewards.py | 0 .../{ => query}/7_DelegatorValidators.py | 0 .../{ => query}/8_DelegatorWithdrawAddress.py | 0 .../{ => query}/9_CommunityPool.py | 0 .../10_MsgSubaccountTransfer.py} | 0 .../11_MsgBatchUpdateOrders.py} | 0 .../12_MsgRewardsOptOut.py} | 0 .../15_ExternalTransfer.py} | 0 .../16_MsgCreateBinaryOptionsLimitOrder.py} | 0 .../17_MsgCreateBinaryOptionsMarketOrder.py} | 0 .../18_MsgCancelBinaryOptionsOrder.py} | 0 .../19_MsgLiquidatePosition.py} | 0 .../1_MsgDeposit.py} | 0 .../3_MsgCreateSpotLimitOrder.py | 0 .../4_MsgCreateSpotMarketOrder.py | 0 .../{ => exchange}/5_MsgCancelSpotOrder.py | 0 .../6_MsgCreateDerivativeLimitOrder.py | 0 .../7_MsgCreateDerivativeMarketOrder.py | 0 .../8_MsgCancelDerivativeOrder.py | 0 .../9_MsgWithdraw.py} | 0 .../exchange/query/10_SpotMarkets.py | 22 + .../exchange/query/11_SpotMarket.py | 21 + .../exchange/query/12_FullSpotMarkets.py | 23 + .../exchange/query/13_FullSpotMarket.py | 22 + .../exchange/query/14_SpotOrderbook.py | 26 + .../exchange/query/15_TraderSpotOrders.py | 37 + .../query/16_AccountAddressSpotOrders.py | 35 + .../exchange/query/17_SpotOrdersByHashes.py | 38 + .../exchange/query/18_SubaccountOrders.py | 37 + .../query/19_TraderSpotTransientOrders.py | 37 + .../exchange/query/1_SubaccountDeposits.py | 34 + .../exchange/query/20_SpotMidPriceAndTOB.py | 21 + .../query/21_DerivativeMidPriceAndTOB.py | 21 + .../exchange/query/22_DerivativeOrderbook.py | 25 + .../query/23_TraderDerivativeOrders.py | 37 + .../24_AccountAddressDerivativeOrders.py | 35 + .../query/25_DerivativeOrdersByHashes.py | 38 + .../26_TraderDerivativeTransientOrders.py | 37 + .../exchange/query/27_DerivativeMarkets.py | 22 + .../exchange/query/28_DerivativeMarket.py | 21 + .../query/29_DerivativeMarketAddress.py | 21 + .../exchange/query/2_SubaccountDeposit.py | 34 + .../exchange/query/30_SubaccountTradeNonce.py | 36 + .../exchange/query/31_Positions.py | 19 + .../exchange/query/32_SubaccountPositions.py | 36 + .../query/33_SubaccountPossitionInMarket.py | 37 + ...34_SubaccountEffectivePossitionInMarket.py | 37 + .../exchange/query/35_PerpetualMarketInfo.py | 21 + .../query/36_ExpiryFuturesMarketInfo.py | 21 + .../query/37_PerpetualMarketFunding.py | 21 + .../query/38_SubaccountOrderMetadata.py | 36 + .../exchange/query/39_TradeRewardPoints.py | 34 + .../exchange/query/3_ExchangeBalances.py | 18 + .../query/40_PendingTradeRewardPoints.py | 34 + .../query/41_FeeDiscountAccountInfo.py | 34 + .../exchange/query/42_FeeDiscountSchedule.py | 19 + .../exchange/query/43_BalanceMismatches.py | 19 + .../query/44_BalanceWithBalanceHolds.py | 19 + .../query/45_FeeDiscountTierStatistics.py | 19 + .../exchange/query/46_MitoVaultInfos.py | 19 + .../query/47_QueryMarketIDFromVault.py | 19 + .../query/48_HistoricalTradeRecords.py | 21 + .../exchange/query/49_IsOptedOutOfRewards.py | 34 + .../exchange/query/4_AggregateVolume.py | 36 + .../query/50_OptedOutOfRewardsAccounts.py | 19 + .../exchange/query/51_MarketVolatility.py | 30 + .../exchange/query/52_BinaryOptionsMarkets.py | 19 + .../53_TraderDerivativeConditionalOrders.py | 37 + .../54_MarketAtomicExecutionFeeMultiplier.py | 21 + .../exchange/query/5_AggregateVolumes.py | 34 + .../exchange/query/6_AggregateMarketVolume.py | 21 + .../query/7_AggregateMarketVolumes.py | 21 + .../exchange/query/8_DenomDecimal.py | 19 + .../exchange/query/9_DenomDecimals.py | 19 + pyinjective/async_client.py | 393 +++ .../chain/grpc/chain_grpc_exchange_api.py | 572 ++++ .../configurable_exchange_query_servicer.py | 325 +++ .../grpc/test_chain_grpc_exchange_api.py | 2466 +++++++++++++++++ 87 files changed, 5229 insertions(+) rename examples/chain_client/distribution/{10_SetWithdrawAddress.py => 1_SetWithdrawAddress.py} (100%) rename examples/chain_client/distribution/{11_WithdrawDelegatorReward.py => 2_WithdrawDelegatorReward.py} (100%) rename examples/chain_client/distribution/{12_WithdrawValidatorCommission.py => 3_WithdrawValidatorCommission.py} (100%) rename examples/chain_client/distribution/{13_FundCommunityPool.py => 4_FundCommunityPool.py} (100%) rename examples/chain_client/distribution/{ => query}/1_ValidatorDistributionInfo.py (100%) rename examples/chain_client/distribution/{ => query}/2_ValidatorOutstandingRewards.py (100%) rename examples/chain_client/distribution/{ => query}/3_ValidatorCommission.py (100%) rename examples/chain_client/distribution/{ => query}/4_ValidatorSlashes.py (100%) rename examples/chain_client/distribution/{ => query}/5_DelegationRewards.py (100%) rename examples/chain_client/distribution/{ => query}/6_DelegationTotalRewards.py (100%) rename examples/chain_client/distribution/{ => query}/7_DelegatorValidators.py (100%) rename examples/chain_client/distribution/{ => query}/8_DelegatorWithdrawAddress.py (100%) rename examples/chain_client/distribution/{ => query}/9_CommunityPool.py (100%) rename examples/chain_client/{16_MsgSubaccountTransfer.py => exchange/10_MsgSubaccountTransfer.py} (100%) rename examples/chain_client/{17_MsgBatchUpdateOrders.py => exchange/11_MsgBatchUpdateOrders.py} (100%) rename examples/chain_client/{24_MsgRewardsOptOut.py => exchange/12_MsgRewardsOptOut.py} (100%) rename examples/chain_client/{30_ExternalTransfer.py => exchange/15_ExternalTransfer.py} (100%) rename examples/chain_client/{31_MsgCreateBinaryOptionsLimitOrder.py => exchange/16_MsgCreateBinaryOptionsLimitOrder.py} (100%) rename examples/chain_client/{32_MsgCreateBinaryOptionsMarketOrder.py => exchange/17_MsgCreateBinaryOptionsMarketOrder.py} (100%) rename examples/chain_client/{33_MsgCancelBinaryOptionsOrder.py => exchange/18_MsgCancelBinaryOptionsOrder.py} (100%) rename examples/chain_client/{77_MsgLiquidatePosition.py => exchange/19_MsgLiquidatePosition.py} (100%) rename examples/chain_client/{2_MsgDeposit.py => exchange/1_MsgDeposit.py} (100%) rename examples/chain_client/{ => exchange}/3_MsgCreateSpotLimitOrder.py (100%) rename examples/chain_client/{ => exchange}/4_MsgCreateSpotMarketOrder.py (100%) rename examples/chain_client/{ => exchange}/5_MsgCancelSpotOrder.py (100%) rename examples/chain_client/{ => exchange}/6_MsgCreateDerivativeLimitOrder.py (100%) rename examples/chain_client/{ => exchange}/7_MsgCreateDerivativeMarketOrder.py (100%) rename examples/chain_client/{ => exchange}/8_MsgCancelDerivativeOrder.py (100%) rename examples/chain_client/{15_MsgWithdraw.py => exchange/9_MsgWithdraw.py} (100%) create mode 100644 examples/chain_client/exchange/query/10_SpotMarkets.py create mode 100644 examples/chain_client/exchange/query/11_SpotMarket.py create mode 100644 examples/chain_client/exchange/query/12_FullSpotMarkets.py create mode 100644 examples/chain_client/exchange/query/13_FullSpotMarket.py create mode 100644 examples/chain_client/exchange/query/14_SpotOrderbook.py create mode 100644 examples/chain_client/exchange/query/15_TraderSpotOrders.py create mode 100644 examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py create mode 100644 examples/chain_client/exchange/query/17_SpotOrdersByHashes.py create mode 100644 examples/chain_client/exchange/query/18_SubaccountOrders.py create mode 100644 examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py create mode 100644 examples/chain_client/exchange/query/1_SubaccountDeposits.py create mode 100644 examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py create mode 100644 examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py create mode 100644 examples/chain_client/exchange/query/22_DerivativeOrderbook.py create mode 100644 examples/chain_client/exchange/query/23_TraderDerivativeOrders.py create mode 100644 examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py create mode 100644 examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py create mode 100644 examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py create mode 100644 examples/chain_client/exchange/query/27_DerivativeMarkets.py create mode 100644 examples/chain_client/exchange/query/28_DerivativeMarket.py create mode 100644 examples/chain_client/exchange/query/29_DerivativeMarketAddress.py create mode 100644 examples/chain_client/exchange/query/2_SubaccountDeposit.py create mode 100644 examples/chain_client/exchange/query/30_SubaccountTradeNonce.py create mode 100644 examples/chain_client/exchange/query/31_Positions.py create mode 100644 examples/chain_client/exchange/query/32_SubaccountPositions.py create mode 100644 examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py create mode 100644 examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py create mode 100644 examples/chain_client/exchange/query/35_PerpetualMarketInfo.py create mode 100644 examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py create mode 100644 examples/chain_client/exchange/query/37_PerpetualMarketFunding.py create mode 100644 examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py create mode 100644 examples/chain_client/exchange/query/39_TradeRewardPoints.py create mode 100644 examples/chain_client/exchange/query/3_ExchangeBalances.py create mode 100644 examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py create mode 100644 examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py create mode 100644 examples/chain_client/exchange/query/42_FeeDiscountSchedule.py create mode 100644 examples/chain_client/exchange/query/43_BalanceMismatches.py create mode 100644 examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py create mode 100644 examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py create mode 100644 examples/chain_client/exchange/query/46_MitoVaultInfos.py create mode 100644 examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py create mode 100644 examples/chain_client/exchange/query/48_HistoricalTradeRecords.py create mode 100644 examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py create mode 100644 examples/chain_client/exchange/query/4_AggregateVolume.py create mode 100644 examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py create mode 100644 examples/chain_client/exchange/query/51_MarketVolatility.py create mode 100644 examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py create mode 100644 examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py create mode 100644 examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py create mode 100644 examples/chain_client/exchange/query/5_AggregateVolumes.py create mode 100644 examples/chain_client/exchange/query/6_AggregateMarketVolume.py create mode 100644 examples/chain_client/exchange/query/7_AggregateMarketVolumes.py create mode 100644 examples/chain_client/exchange/query/8_DenomDecimal.py create mode 100644 examples/chain_client/exchange/query/9_DenomDecimals.py create mode 100644 pyinjective/client/chain/grpc/chain_grpc_exchange_api.py create mode 100644 tests/client/chain/grpc/configurable_exchange_query_servicer.py create mode 100644 tests/client/chain/grpc/test_chain_grpc_exchange_api.py diff --git a/examples/chain_client/distribution/10_SetWithdrawAddress.py b/examples/chain_client/distribution/1_SetWithdrawAddress.py similarity index 100% rename from examples/chain_client/distribution/10_SetWithdrawAddress.py rename to examples/chain_client/distribution/1_SetWithdrawAddress.py diff --git a/examples/chain_client/distribution/11_WithdrawDelegatorReward.py b/examples/chain_client/distribution/2_WithdrawDelegatorReward.py similarity index 100% rename from examples/chain_client/distribution/11_WithdrawDelegatorReward.py rename to examples/chain_client/distribution/2_WithdrawDelegatorReward.py diff --git a/examples/chain_client/distribution/12_WithdrawValidatorCommission.py b/examples/chain_client/distribution/3_WithdrawValidatorCommission.py similarity index 100% rename from examples/chain_client/distribution/12_WithdrawValidatorCommission.py rename to examples/chain_client/distribution/3_WithdrawValidatorCommission.py diff --git a/examples/chain_client/distribution/13_FundCommunityPool.py b/examples/chain_client/distribution/4_FundCommunityPool.py similarity index 100% rename from examples/chain_client/distribution/13_FundCommunityPool.py rename to examples/chain_client/distribution/4_FundCommunityPool.py diff --git a/examples/chain_client/distribution/1_ValidatorDistributionInfo.py b/examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py similarity index 100% rename from examples/chain_client/distribution/1_ValidatorDistributionInfo.py rename to examples/chain_client/distribution/query/1_ValidatorDistributionInfo.py diff --git a/examples/chain_client/distribution/2_ValidatorOutstandingRewards.py b/examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py similarity index 100% rename from examples/chain_client/distribution/2_ValidatorOutstandingRewards.py rename to examples/chain_client/distribution/query/2_ValidatorOutstandingRewards.py diff --git a/examples/chain_client/distribution/3_ValidatorCommission.py b/examples/chain_client/distribution/query/3_ValidatorCommission.py similarity index 100% rename from examples/chain_client/distribution/3_ValidatorCommission.py rename to examples/chain_client/distribution/query/3_ValidatorCommission.py diff --git a/examples/chain_client/distribution/4_ValidatorSlashes.py b/examples/chain_client/distribution/query/4_ValidatorSlashes.py similarity index 100% rename from examples/chain_client/distribution/4_ValidatorSlashes.py rename to examples/chain_client/distribution/query/4_ValidatorSlashes.py diff --git a/examples/chain_client/distribution/5_DelegationRewards.py b/examples/chain_client/distribution/query/5_DelegationRewards.py similarity index 100% rename from examples/chain_client/distribution/5_DelegationRewards.py rename to examples/chain_client/distribution/query/5_DelegationRewards.py diff --git a/examples/chain_client/distribution/6_DelegationTotalRewards.py b/examples/chain_client/distribution/query/6_DelegationTotalRewards.py similarity index 100% rename from examples/chain_client/distribution/6_DelegationTotalRewards.py rename to examples/chain_client/distribution/query/6_DelegationTotalRewards.py diff --git a/examples/chain_client/distribution/7_DelegatorValidators.py b/examples/chain_client/distribution/query/7_DelegatorValidators.py similarity index 100% rename from examples/chain_client/distribution/7_DelegatorValidators.py rename to examples/chain_client/distribution/query/7_DelegatorValidators.py diff --git a/examples/chain_client/distribution/8_DelegatorWithdrawAddress.py b/examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py similarity index 100% rename from examples/chain_client/distribution/8_DelegatorWithdrawAddress.py rename to examples/chain_client/distribution/query/8_DelegatorWithdrawAddress.py diff --git a/examples/chain_client/distribution/9_CommunityPool.py b/examples/chain_client/distribution/query/9_CommunityPool.py similarity index 100% rename from examples/chain_client/distribution/9_CommunityPool.py rename to examples/chain_client/distribution/query/9_CommunityPool.py diff --git a/examples/chain_client/16_MsgSubaccountTransfer.py b/examples/chain_client/exchange/10_MsgSubaccountTransfer.py similarity index 100% rename from examples/chain_client/16_MsgSubaccountTransfer.py rename to examples/chain_client/exchange/10_MsgSubaccountTransfer.py diff --git a/examples/chain_client/17_MsgBatchUpdateOrders.py b/examples/chain_client/exchange/11_MsgBatchUpdateOrders.py similarity index 100% rename from examples/chain_client/17_MsgBatchUpdateOrders.py rename to examples/chain_client/exchange/11_MsgBatchUpdateOrders.py diff --git a/examples/chain_client/24_MsgRewardsOptOut.py b/examples/chain_client/exchange/12_MsgRewardsOptOut.py similarity index 100% rename from examples/chain_client/24_MsgRewardsOptOut.py rename to examples/chain_client/exchange/12_MsgRewardsOptOut.py diff --git a/examples/chain_client/30_ExternalTransfer.py b/examples/chain_client/exchange/15_ExternalTransfer.py similarity index 100% rename from examples/chain_client/30_ExternalTransfer.py rename to examples/chain_client/exchange/15_ExternalTransfer.py diff --git a/examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py similarity index 100% rename from examples/chain_client/31_MsgCreateBinaryOptionsLimitOrder.py rename to examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py diff --git a/examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py similarity index 100% rename from examples/chain_client/32_MsgCreateBinaryOptionsMarketOrder.py rename to examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py diff --git a/examples/chain_client/33_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py similarity index 100% rename from examples/chain_client/33_MsgCancelBinaryOptionsOrder.py rename to examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py diff --git a/examples/chain_client/77_MsgLiquidatePosition.py b/examples/chain_client/exchange/19_MsgLiquidatePosition.py similarity index 100% rename from examples/chain_client/77_MsgLiquidatePosition.py rename to examples/chain_client/exchange/19_MsgLiquidatePosition.py diff --git a/examples/chain_client/2_MsgDeposit.py b/examples/chain_client/exchange/1_MsgDeposit.py similarity index 100% rename from examples/chain_client/2_MsgDeposit.py rename to examples/chain_client/exchange/1_MsgDeposit.py diff --git a/examples/chain_client/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py similarity index 100% rename from examples/chain_client/3_MsgCreateSpotLimitOrder.py rename to examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py diff --git a/examples/chain_client/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py similarity index 100% rename from examples/chain_client/4_MsgCreateSpotMarketOrder.py rename to examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py diff --git a/examples/chain_client/5_MsgCancelSpotOrder.py b/examples/chain_client/exchange/5_MsgCancelSpotOrder.py similarity index 100% rename from examples/chain_client/5_MsgCancelSpotOrder.py rename to examples/chain_client/exchange/5_MsgCancelSpotOrder.py diff --git a/examples/chain_client/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py similarity index 100% rename from examples/chain_client/6_MsgCreateDerivativeLimitOrder.py rename to examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py diff --git a/examples/chain_client/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py similarity index 100% rename from examples/chain_client/7_MsgCreateDerivativeMarketOrder.py rename to examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py diff --git a/examples/chain_client/8_MsgCancelDerivativeOrder.py b/examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py similarity index 100% rename from examples/chain_client/8_MsgCancelDerivativeOrder.py rename to examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py diff --git a/examples/chain_client/15_MsgWithdraw.py b/examples/chain_client/exchange/9_MsgWithdraw.py similarity index 100% rename from examples/chain_client/15_MsgWithdraw.py rename to examples/chain_client/exchange/9_MsgWithdraw.py diff --git a/examples/chain_client/exchange/query/10_SpotMarkets.py b/examples/chain_client/exchange/query/10_SpotMarkets.py new file mode 100644 index 00000000..4cedc9d7 --- /dev/null +++ b/examples/chain_client/exchange/query/10_SpotMarkets.py @@ -0,0 +1,22 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_markets = await client.fetch_chain_spot_markets( + status="Active", + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(spot_markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/11_SpotMarket.py b/examples/chain_client/exchange/query/11_SpotMarket.py new file mode 100644 index 00000000..0e774edf --- /dev/null +++ b/examples/chain_client/exchange/query/11_SpotMarket.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_market = await client.fetch_chain_spot_market( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(spot_market) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/12_FullSpotMarkets.py b/examples/chain_client/exchange/query/12_FullSpotMarkets.py new file mode 100644 index 00000000..cfefee28 --- /dev/null +++ b/examples/chain_client/exchange/query/12_FullSpotMarkets.py @@ -0,0 +1,23 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_markets = await client.fetch_chain_full_spot_markets( + status="Active", + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + with_mid_price_and_tob=True, + ) + print(spot_markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/13_FullSpotMarket.py b/examples/chain_client/exchange/query/13_FullSpotMarket.py new file mode 100644 index 00000000..6a39269d --- /dev/null +++ b/examples/chain_client/exchange/query/13_FullSpotMarket.py @@ -0,0 +1,22 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + spot_market = await client.fetch_chain_full_spot_market( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + with_mid_price_and_tob=True, + ) + print(spot_market) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/14_SpotOrderbook.py b/examples/chain_client/exchange/query/14_SpotOrderbook.py new file mode 100644 index 00000000..7b5a9aa1 --- /dev/null +++ b/examples/chain_client/exchange/query/14_SpotOrderbook.py @@ -0,0 +1,26 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + pagination = PaginationOption(limit=2) + + orderbook = await client.fetch_chain_spot_orderbook( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + order_side="Buy", + pagination=pagination, + ) + print(orderbook) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/15_TraderSpotOrders.py b/examples/chain_client/exchange/query/15_TraderSpotOrders.py new file mode 100644 index 00000000..0cc96b6f --- /dev/null +++ b/examples/chain_client/exchange/query/15_TraderSpotOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_trader_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py b/examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py new file mode 100644 index 00000000..8e50fa95 --- /dev/null +++ b/examples/chain_client/exchange/query/16_AccountAddressSpotOrders.py @@ -0,0 +1,35 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + orders = await client.fetch_chain_account_address_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + account_address=address.to_acc_bech32(), + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/17_SpotOrdersByHashes.py b/examples/chain_client/exchange/query/17_SpotOrdersByHashes.py new file mode 100644 index 00000000..641eb6f5 --- /dev/null +++ b/examples/chain_client/exchange/query/17_SpotOrdersByHashes.py @@ -0,0 +1,38 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_spot_orders_by_hashes( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id=subaccount_id, + order_hashes=["0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"], + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/18_SubaccountOrders.py b/examples/chain_client/exchange/query/18_SubaccountOrders.py new file mode 100644 index 00000000..4983f827 --- /dev/null +++ b/examples/chain_client/exchange/query/18_SubaccountOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_subaccount_orders( + subaccount_id=subaccount_id, + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py b/examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py new file mode 100644 index 00000000..2b29c2c0 --- /dev/null +++ b/examples/chain_client/exchange/query/19_TraderSpotTransientOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_trader_spot_transient_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/1_SubaccountDeposits.py b/examples/chain_client/exchange/query/1_SubaccountDeposits.py new file mode 100644 index 00000000..f9afb8ae --- /dev/null +++ b/examples/chain_client/exchange/query/1_SubaccountDeposits.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + deposits = await client.fetch_subaccount_deposits(subaccount_id=subaccount_id) + print(deposits) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py b/examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py new file mode 100644 index 00000000..35493ffd --- /dev/null +++ b/examples/chain_client/exchange/query/20_SpotMidPriceAndTOB.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + prices = await client.fetch_spot_mid_price_and_tob( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + print(prices) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py b/examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py new file mode 100644 index 00000000..5b5c5fff --- /dev/null +++ b/examples/chain_client/exchange/query/21_DerivativeMidPriceAndTOB.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + prices = await client.fetch_derivative_mid_price_and_tob( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(prices) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/22_DerivativeOrderbook.py b/examples/chain_client/exchange/query/22_DerivativeOrderbook.py new file mode 100644 index 00000000..465a62b6 --- /dev/null +++ b/examples/chain_client/exchange/query/22_DerivativeOrderbook.py @@ -0,0 +1,25 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + pagination = PaginationOption(limit=2) + + orderbook = await client.fetch_chain_derivative_orderbook( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + pagination=pagination, + ) + print(orderbook) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py b/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py new file mode 100644 index 00000000..61e98ba1 --- /dev/null +++ b/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_trader_spot_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py b/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py new file mode 100644 index 00000000..469c99fb --- /dev/null +++ b/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py @@ -0,0 +1,35 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + orders = await client.fetch_chain_account_address_spot_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + account_address=address.to_acc_bech32(), + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py b/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py new file mode 100644 index 00000000..ea700e6d --- /dev/null +++ b/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py @@ -0,0 +1,38 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_spot_orders_by_hashes( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id=subaccount_id, + order_hashes=["0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"], + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py b/examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py new file mode 100644 index 00000000..c5548d59 --- /dev/null +++ b/examples/chain_client/exchange/query/26_TraderDerivativeTransientOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_chain_trader_derivative_transient_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id=subaccount_id, + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/27_DerivativeMarkets.py b/examples/chain_client/exchange/query/27_DerivativeMarkets.py new file mode 100644 index 00000000..2f4bbc5a --- /dev/null +++ b/examples/chain_client/exchange/query/27_DerivativeMarkets.py @@ -0,0 +1,22 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + derivative_markets = await client.fetch_chain_derivative_markets( + status="Active", + market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"], + ) + print(derivative_markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/28_DerivativeMarket.py b/examples/chain_client/exchange/query/28_DerivativeMarket.py new file mode 100644 index 00000000..152381f5 --- /dev/null +++ b/examples/chain_client/exchange/query/28_DerivativeMarket.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + derivative_market = await client.fetch_chain_derivative_market( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(derivative_market) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/29_DerivativeMarketAddress.py b/examples/chain_client/exchange/query/29_DerivativeMarketAddress.py new file mode 100644 index 00000000..c2d88805 --- /dev/null +++ b/examples/chain_client/exchange/query/29_DerivativeMarketAddress.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + address = await client.fetch_derivative_market_address( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(address) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/2_SubaccountDeposit.py b/examples/chain_client/exchange/query/2_SubaccountDeposit.py new file mode 100644 index 00000000..5002397d --- /dev/null +++ b/examples/chain_client/exchange/query/2_SubaccountDeposit.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + deposit = await client.fetch_subaccount_deposit(subaccount_id=subaccount_id, denom="inj") + print(deposit) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/30_SubaccountTradeNonce.py b/examples/chain_client/exchange/query/30_SubaccountTradeNonce.py new file mode 100644 index 00000000..ad81aca3 --- /dev/null +++ b/examples/chain_client/exchange/query/30_SubaccountTradeNonce.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + nonce = await client.fetch_subaccount_trade_nonce( + subaccount_id=subaccount_id, + ) + print(nonce) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/31_Positions.py b/examples/chain_client/exchange/query/31_Positions.py new file mode 100644 index 00000000..ae494b6a --- /dev/null +++ b/examples/chain_client/exchange/query/31_Positions.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + positions = await client.fetch_chain_positions() + print(positions) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/32_SubaccountPositions.py b/examples/chain_client/exchange/query/32_SubaccountPositions.py new file mode 100644 index 00000000..000d95b6 --- /dev/null +++ b/examples/chain_client/exchange/query/32_SubaccountPositions.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + positions = await client.fetch_chain_subaccount_positions( + subaccount_id=subaccount_id, + ) + print(positions) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py b/examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py new file mode 100644 index 00000000..4e0f1ddb --- /dev/null +++ b/examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + position = await client.fetch_chain_subaccount_position_in_market( + subaccount_id=subaccount_id, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(position) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py b/examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py new file mode 100644 index 00000000..e729e77c --- /dev/null +++ b/examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + position = await client.fetch_chain_subaccount_effective_position_in_market( + subaccount_id=subaccount_id, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(position) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/35_PerpetualMarketInfo.py b/examples/chain_client/exchange/query/35_PerpetualMarketInfo.py new file mode 100644 index 00000000..ca27f552 --- /dev/null +++ b/examples/chain_client/exchange/query/35_PerpetualMarketInfo.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_info = await client.fetch_chain_perpetual_market_info( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(market_info) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py b/examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py new file mode 100644 index 00000000..4053013c --- /dev/null +++ b/examples/chain_client/exchange/query/36_ExpiryFuturesMarketInfo.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_info = await client.fetch_chain_expiry_futures_market_info( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(market_info) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/37_PerpetualMarketFunding.py b/examples/chain_client/exchange/query/37_PerpetualMarketFunding.py new file mode 100644 index 00000000..099c2a0f --- /dev/null +++ b/examples/chain_client/exchange/query/37_PerpetualMarketFunding.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + funding = await client.fetch_chain_perpetual_market_funding( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(funding) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py b/examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py new file mode 100644 index 00000000..f4af9d38 --- /dev/null +++ b/examples/chain_client/exchange/query/38_SubaccountOrderMetadata.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + metadata = await client.fetch_subaccount_order_metadata( + subaccount_id=subaccount_id, + ) + print(metadata) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/39_TradeRewardPoints.py b/examples/chain_client/exchange/query/39_TradeRewardPoints.py new file mode 100644 index 00000000..13f08730 --- /dev/null +++ b/examples/chain_client/exchange/query/39_TradeRewardPoints.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + points = await client.fetch_trade_reward_points( + accounts=[address.to_acc_bech32()], + ) + print(points) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/3_ExchangeBalances.py b/examples/chain_client/exchange/query/3_ExchangeBalances.py new file mode 100644 index 00000000..091bf10c --- /dev/null +++ b/examples/chain_client/exchange/query/3_ExchangeBalances.py @@ -0,0 +1,18 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + # initialize grpc client + client = AsyncClient(network) + + balances = await client.fetch_exchange_balances() + print(balances) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py b/examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py new file mode 100644 index 00000000..fa3e8aa2 --- /dev/null +++ b/examples/chain_client/exchange/query/40_PendingTradeRewardPoints.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + points = await client.fetch_pending_trade_reward_points( + accounts=[address.to_acc_bech32()], + ) + print(points) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py b/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py new file mode 100644 index 00000000..15fbb7ce --- /dev/null +++ b/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + fee_discount = await client.fetch_fee_discount_account_info( + account=address.to_acc_bech32(), + ) + print(fee_discount) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py b/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py new file mode 100644 index 00000000..a0ae96cb --- /dev/null +++ b/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + schedule = await client.fetch_fee_discount_schedule() + print(schedule) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/43_BalanceMismatches.py b/examples/chain_client/exchange/query/43_BalanceMismatches.py new file mode 100644 index 00000000..c7f7ca5e --- /dev/null +++ b/examples/chain_client/exchange/query/43_BalanceMismatches.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + mismatches = await client.fetch_balance_mismatches(dust_factor=1) + print(mismatches) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py b/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py new file mode 100644 index 00000000..6587c59a --- /dev/null +++ b/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + balance = await client.fetch_balance_with_balance_holds() + print(balance) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py b/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py new file mode 100644 index 00000000..5671e4ce --- /dev/null +++ b/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + statistics = await client.fetch_fee_discount_tier_statistics() + print(statistics) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/46_MitoVaultInfos.py b/examples/chain_client/exchange/query/46_MitoVaultInfos.py new file mode 100644 index 00000000..3faa5cb9 --- /dev/null +++ b/examples/chain_client/exchange/query/46_MitoVaultInfos.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + infos = await client.fetch_mito_vault_infos() + print(infos) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py b/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py new file mode 100644 index 00000000..e699dbaa --- /dev/null +++ b/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_id = await client.fetch_market_id_from_vault(vault_address="inj1qg5ega6dykkxc307y25pecuufrjkxkag6xhp6y") + print(market_id) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py b/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py new file mode 100644 index 00000000..6b93200f --- /dev/null +++ b/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + records = await client.fetch_historical_trade_records( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + ) + print(records) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py b/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py new file mode 100644 index 00000000..28c0925c --- /dev/null +++ b/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + is_opted_out = await client.fetch_is_opted_out_of_rewards( + account=address.to_acc_bech32(), + ) + print(is_opted_out) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/4_AggregateVolume.py b/examples/chain_client/exchange/query/4_AggregateVolume.py new file mode 100644 index 00000000..35c334a5 --- /dev/null +++ b/examples/chain_client/exchange/query/4_AggregateVolume.py @@ -0,0 +1,36 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + + subaccount_id = address.get_subaccount_id(index=0) + + volume = await client.fetch_aggregate_volume(account=address.to_acc_bech32()) + print(volume) + + volume = await client.fetch_aggregate_volume(account=subaccount_id) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py b/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py new file mode 100644 index 00000000..9940f799 --- /dev/null +++ b/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + opted_out = await client.fetch_opted_out_of_rewards_accounts() + print(opted_out) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/51_MarketVolatility.py b/examples/chain_client/exchange/query/51_MarketVolatility.py new file mode 100644 index 00000000..3173ca39 --- /dev/null +++ b/examples/chain_client/exchange/query/51_MarketVolatility.py @@ -0,0 +1,30 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + trade_grouping_sec = 10 + max_age = 0 + include_raw_history = True + include_metadata = True + volatility = await client.fetch_market_volatility( + market_id=market_id, + trade_grouping_sec=trade_grouping_sec, + max_age=max_age, + include_raw_history=include_raw_history, + include_metadata=include_metadata, + ) + print(volatility) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py b/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py new file mode 100644 index 00000000..4448a4ec --- /dev/null +++ b/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + markets = await client.fetch_chain_binary_options_markets(status="Active") + print(markets) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py b/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py new file mode 100644 index 00000000..fd65e68f --- /dev/null +++ b/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py @@ -0,0 +1,37 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + subaccount_id = address.get_subaccount_id(index=0) + + orders = await client.fetch_trader_derivative_conditional_orders( + subaccount_id=subaccount_id, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(orders) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py b/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py new file mode 100644 index 00000000..328028d3 --- /dev/null +++ b/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + multiplier = await client.fetch_market_atomic_execution_fee_multiplier( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + print(multiplier) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/5_AggregateVolumes.py b/examples/chain_client/exchange/query/5_AggregateVolumes.py new file mode 100644 index 00000000..6effe4be --- /dev/null +++ b/examples/chain_client/exchange/query/5_AggregateVolumes.py @@ -0,0 +1,34 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + + volume = await client.fetch_aggregate_volumes( + accounts=[address.to_acc_bech32()], + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/6_AggregateMarketVolume.py b/examples/chain_client/exchange/query/6_AggregateMarketVolume.py new file mode 100644 index 00000000..b3262d82 --- /dev/null +++ b/examples/chain_client/exchange/query/6_AggregateMarketVolume.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + + volume = await client.fetch_aggregate_market_volume(market_id=market_id) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/7_AggregateMarketVolumes.py b/examples/chain_client/exchange/query/7_AggregateMarketVolumes.py new file mode 100644 index 00000000..23dfa0ec --- /dev/null +++ b/examples/chain_client/exchange/query/7_AggregateMarketVolumes.py @@ -0,0 +1,21 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + volume = await client.fetch_aggregate_market_volumes( + market_ids=["0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe"], + ) + print(volume) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/8_DenomDecimal.py b/examples/chain_client/exchange/query/8_DenomDecimal.py new file mode 100644 index 00000000..2079f5e8 --- /dev/null +++ b/examples/chain_client/exchange/query/8_DenomDecimal.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + deposits = await client.fetch_denom_decimal(denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5") + print(deposits) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/9_DenomDecimals.py b/examples/chain_client/exchange/query/9_DenomDecimals.py new file mode 100644 index 00000000..d96df30b --- /dev/null +++ b/examples/chain_client/exchange/query/9_DenomDecimals.py @@ -0,0 +1,19 @@ +import asyncio + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + deposits = await client.fetch_denom_decimals(denoms=["inj", "peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"]) + print(deposits) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index dea12f12..0af37da0 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -13,6 +13,7 @@ from pyinjective.client.chain.grpc.chain_grpc_authz_api import ChainGrpcAuthZApi from pyinjective.client.chain.grpc.chain_grpc_bank_api import ChainGrpcBankApi from pyinjective.client.chain.grpc.chain_grpc_distribution_api import ChainGrpcDistributionApi +from pyinjective.client.chain.grpc.chain_grpc_exchange_api import ChainGrpcExchangeApi from pyinjective.client.chain.grpc.chain_grpc_token_factory_api import ChainGrpcTokenFactoryApi from pyinjective.client.chain.grpc.chain_grpc_wasm_api import ChainGrpcWasmApi from pyinjective.client.chain.grpc_stream.chain_grpc_chain_stream import ChainGrpcChainStream @@ -185,6 +186,12 @@ def __init__( metadata_query_provider=self._chain_cookie_metadata_requestor ), ) + self.chain_exchange_api = ChainGrpcExchangeApi( + channel=self.chain_channel, + metadata_provider=lambda: self.network.chain_metadata( + metadata_query_provider=self._chain_cookie_metadata_requestor + ), + ) self.token_factory_api = ChainGrpcTokenFactoryApi( channel=self.chain_channel, metadata_provider=lambda: self.network.chain_metadata( @@ -639,6 +646,392 @@ async def fetch_delegator_withdraw_address( async def fetch_community_pool(self) -> Dict[str, Any]: return await self.distribution_api.fetch_community_pool() + # Exchange module + + async def fetch_subaccount_deposits( + self, + subaccount_id: Optional[str] = None, + subaccount_trader: Optional[str] = None, + subaccount_nonce: Optional[int] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_deposits( + subaccount_id=subaccount_id, + subaccount_trader=subaccount_trader, + subaccount_nonce=subaccount_nonce, + ) + + async def fetch_subaccount_deposit( + self, + subaccount_id: str, + denom: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_deposit( + subaccount_id=subaccount_id, + denom=denom, + ) + + async def fetch_exchange_balances(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_exchange_balances() + + async def fetch_aggregate_volume(self, account: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_volume(account=account) + + async def fetch_aggregate_volumes( + self, + accounts: Optional[List[str]] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_volumes( + accounts=accounts, + market_ids=market_ids, + ) + + async def fetch_aggregate_market_volume( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_market_volume( + market_id=market_id, + ) + + async def fetch_aggregate_market_volumes( + self, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_aggregate_market_volumes( + market_ids=market_ids, + ) + + async def fetch_denom_decimal(self, denom: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_denom_decimal(denom=denom) + + async def fetch_denom_decimals(self, denoms: Optional[List[str]] = None) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_denom_decimals(denoms=denoms) + + async def fetch_chain_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_markets( + status=status, + market_ids=market_ids, + ) + + async def fetch_chain_spot_market( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_market( + market_id=market_id, + ) + + async def fetch_chain_full_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_full_spot_markets( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + + async def fetch_chain_full_spot_market( + self, + market_id: str, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_full_spot_market( + market_id=market_id, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + + async def fetch_chain_spot_orderbook( + self, + market_id: str, + order_side: Optional[str] = None, + limit_cumulative_notional: Optional[str] = None, + limit_cumulative_quantity: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + # Order side could be "Side_Unspecified", "Buy", "Sell" + return await self.chain_exchange_api.fetch_spot_orderbook( + market_id=market_id, + order_side=order_side, + limit_cumulative_notional=limit_cumulative_notional, + limit_cumulative_quantity=limit_cumulative_quantity, + pagination=pagination, + ) + + async def fetch_chain_trader_spot_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_spot_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_chain_account_address_spot_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_account_address_spot_orders( + market_id=market_id, + account_address=account_address, + ) + + async def fetch_chain_spot_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_orders_by_hashes( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + + async def fetch_chain_subaccount_orders( + self, + subaccount_id: str, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_orders( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_chain_trader_spot_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_spot_transient_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_spot_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_spot_mid_price_and_tob( + market_id=market_id, + ) + + async def fetch_derivative_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_mid_price_and_tob( + market_id=market_id, + ) + + async def fetch_chain_derivative_orderbook( + self, + market_id: str, + limit_cumulative_notional: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_orderbook( + market_id=market_id, + limit_cumulative_notional=limit_cumulative_notional, + pagination=pagination, + ) + + async def fetch_chain_trader_derivative_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_derivative_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_chain_account_address_derivative_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_account_address_derivative_orders( + market_id=market_id, + account_address=account_address, + ) + + async def fetch_chain_derivative_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_orders_by_hashes( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + + async def fetch_chain_trader_derivative_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_derivative_transient_orders( + market_id=market_id, + subaccount_id=subaccount_id, + ) + + async def fetch_chain_derivative_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_markets( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + + async def fetch_chain_derivative_market( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_market( + market_id=market_id, + ) + + async def fetch_derivative_market_address(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_derivative_market_address(market_id=market_id) + + async def fetch_subaccount_trade_nonce(self, subaccount_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_trade_nonce(subaccount_id=subaccount_id) + + async def fetch_chain_positions(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_positions() + + async def fetch_chain_subaccount_positions(self, subaccount_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_positions(subaccount_id=subaccount_id) + + async def fetch_chain_subaccount_position_in_market(self, subaccount_id: str, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_chain_subaccount_effective_position_in_market( + self, subaccount_id: str, market_id: str + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_effective_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_chain_perpetual_market_info(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_perpetual_market_info(market_id=market_id) + + async def fetch_chain_expiry_futures_market_info(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_expiry_futures_market_info(market_id=market_id) + + async def fetch_chain_perpetual_market_funding(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_perpetual_market_funding(market_id=market_id) + + async def fetch_subaccount_order_metadata(self, subaccount_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_subaccount_order_metadata(subaccount_id=subaccount_id) + + async def fetch_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trade_reward_points( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + + async def fetch_pending_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_pending_trade_reward_points( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + + async def fetch_fee_discount_account_info(self, account: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_fee_discount_account_info(account=account) + + async def fetch_fee_discount_schedule(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_fee_discount_schedule() + + async def fetch_balance_mismatches(self, dust_factor: int) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_balance_mismatches(dust_factor=dust_factor) + + async def fetch_balance_with_balance_holds(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_balance_with_balance_holds() + + async def fetch_fee_discount_tier_statistics(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_fee_discount_tier_statistics() + + async def fetch_mito_vault_infos(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_mito_vault_infos() + + async def fetch_market_id_from_vault(self, vault_address: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_market_id_from_vault(vault_address=vault_address) + + async def fetch_historical_trade_records(self, market_id: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_historical_trade_records(market_id=market_id) + + async def fetch_is_opted_out_of_rewards(self, account: str) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_is_opted_out_of_rewards(account=account) + + async def fetch_opted_out_of_rewards_accounts(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_opted_out_of_rewards_accounts() + + async def fetch_market_volatility( + self, + market_id: str, + trade_grouping_sec: Optional[int] = None, + max_age: Optional[int] = None, + include_raw_history: Optional[bool] = None, + include_metadata: Optional[bool] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_market_volatility( + market_id=market_id, + trade_grouping_sec=trade_grouping_sec, + max_age=max_age, + include_raw_history=include_raw_history, + include_metadata=include_metadata, + ) + + async def fetch_chain_binary_options_markets(self, status: Optional[str] = None) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_binary_options_markets(status=status) + + async def fetch_trader_derivative_conditional_orders( + self, + subaccount_id: Optional[str] = None, + market_id: Optional[str] = None, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trader_derivative_conditional_orders( + subaccount_id=subaccount_id, + market_id=market_id, + ) + + async def fetch_market_atomic_execution_fee_multiplier( + self, + market_id: str, + ) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_market_atomic_execution_fee_multiplier( + market_id=market_id, + ) + # Injective Exchange client methods # Auction RPC diff --git a/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py b/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py new file mode 100644 index 00000000..217c0d34 --- /dev/null +++ b/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py @@ -0,0 +1,572 @@ +from typing import Any, Callable, Dict, List, Optional + +from grpc.aio import Channel + +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.proto.injective.exchange.v1beta1 import ( + query_pb2 as exchange_query_pb, + query_pb2_grpc as exchange_query_grpc, +) +from pyinjective.utils.grpc_api_request_assistant import GrpcApiRequestAssistant + + +class ChainGrpcExchangeApi: + def __init__(self, channel: Channel, metadata_provider: Callable): + self._stub = exchange_query_grpc.QueryStub(channel) + self._assistant = GrpcApiRequestAssistant(metadata_provider=metadata_provider) + + async def fetch_exchange_params(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryExchangeParamsRequest() + response = await self._execute_call(call=self._stub.QueryExchangeParams, request=request) + + return response + + async def fetch_subaccount_deposits( + self, + subaccount_id: Optional[str] = None, + subaccount_trader: Optional[str] = None, + subaccount_nonce: Optional[int] = None, + ) -> Dict[str, Any]: + subaccount = None + if subaccount_trader is not None or subaccount_nonce is not None: + subaccount = exchange_query_pb.Subaccount( + trader=subaccount_trader, + subaccount_nonce=subaccount_nonce, + ) + + request = exchange_query_pb.QuerySubaccountDepositsRequest(subaccount_id=subaccount_id, subaccount=subaccount) + response = await self._execute_call(call=self._stub.SubaccountDeposits, request=request) + + return response + + async def fetch_subaccount_deposit( + self, + subaccount_id: str, + denom: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountDepositRequest( + subaccount_id=subaccount_id, + denom=denom, + ) + response = await self._execute_call(call=self._stub.SubaccountDeposit, request=request) + + return response + + async def fetch_exchange_balances(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryExchangeBalancesRequest() + response = await self._execute_call(call=self._stub.ExchangeBalances, request=request) + + return response + + async def fetch_aggregate_volume(self, account: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateVolumeRequest(account=account) + response = await self._execute_call(call=self._stub.AggregateVolume, request=request) + + return response + + async def fetch_aggregate_volumes( + self, + accounts: Optional[List[str]] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateVolumesRequest(accounts=accounts, market_ids=market_ids) + response = await self._execute_call(call=self._stub.AggregateVolumes, request=request) + + return response + + async def fetch_aggregate_market_volume(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateMarketVolumeRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.AggregateMarketVolume, request=request) + + return response + + async def fetch_aggregate_market_volumes(self, market_ids: Optional[List[str]] = None) -> Dict[str, Any]: + request = exchange_query_pb.QueryAggregateMarketVolumesRequest(market_ids=market_ids) + response = await self._execute_call(call=self._stub.AggregateMarketVolumes, request=request) + + return response + + async def fetch_denom_decimal(self, denom: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryDenomDecimalRequest(denom=denom) + response = await self._execute_call(call=self._stub.DenomDecimal, request=request) + + return response + + async def fetch_denom_decimals(self, denoms: Optional[List[str]] = None) -> Dict[str, Any]: + request = exchange_query_pb.QueryDenomDecimalsRequest(denoms=denoms) + response = await self._execute_call(call=self._stub.DenomDecimals, request=request) + + return response + + async def fetch_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotMarketsRequest( + status=status, + market_ids=market_ids, + ) + response = await self._execute_call(call=self._stub.SpotMarkets, request=request) + + return response + + async def fetch_spot_market(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotMarketRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.SpotMarket, request=request) + + return response + + async def fetch_full_spot_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFullSpotMarketsRequest( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + response = await self._execute_call(call=self._stub.FullSpotMarkets, request=request) + + return response + + async def fetch_full_spot_market( + self, + market_id: str, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFullSpotMarketRequest( + market_id=market_id, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + response = await self._execute_call(call=self._stub.FullSpotMarket, request=request) + + return response + + async def fetch_spot_orderbook( + self, + market_id: str, + order_side: Optional[str] = None, + limit_cumulative_notional: Optional[str] = None, + limit_cumulative_quantity: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + limit = None + if pagination is not None: + limit = pagination.limit + request = exchange_query_pb.QuerySpotOrderbookRequest( + market_id=market_id, + order_side=order_side, + limit=limit, + limit_cumulative_notional=limit_cumulative_notional, + limit_cumulative_quantity=limit_cumulative_quantity, + ) + response = await self._execute_call(call=self._stub.SpotOrderbook, request=request) + + return response + + async def fetch_trader_spot_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderSpotOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderSpotOrders, request=request) + + return response + + async def fetch_account_address_spot_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryAccountAddressSpotOrdersRequest( + market_id=market_id, + account_address=account_address, + ) + response = await self._execute_call(call=self._stub.AccountAddressSpotOrders, request=request) + + return response + + async def fetch_spot_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotOrdersByHashesRequest( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + response = await self._execute_call(call=self._stub.SpotOrdersByHashes, request=request) + + return response + + async def fetch_subaccount_orders( + self, + subaccount_id: str, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountOrdersRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SubaccountOrders, request=request) + + return response + + async def fetch_trader_spot_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderSpotOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderSpotTransientOrders, request=request) + + return response + + async def fetch_spot_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QuerySpotMidPriceAndTOBRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SpotMidPriceAndTOB, request=request) + + return response + + async def fetch_derivative_mid_price_and_tob( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMidPriceAndTOBRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.DerivativeMidPriceAndTOB, request=request) + + return response + + async def fetch_derivative_orderbook( + self, + market_id: str, + limit_cumulative_notional: Optional[str] = None, + pagination: Optional[PaginationOption] = None, + ) -> Dict[str, Any]: + limit = None + if pagination is not None: + limit = pagination.limit + request = exchange_query_pb.QueryDerivativeOrderbookRequest( + market_id=market_id, + limit=limit, + limit_cumulative_notional=limit_cumulative_notional, + ) + response = await self._execute_call(call=self._stub.DerivativeOrderbook, request=request) + + return response + + async def fetch_trader_derivative_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderDerivativeOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderDerivativeOrders, request=request) + + return response + + async def fetch_account_address_derivative_orders( + self, + market_id: str, + account_address: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryAccountAddressDerivativeOrdersRequest( + market_id=market_id, + account_address=account_address, + ) + response = await self._execute_call(call=self._stub.AccountAddressDerivativeOrders, request=request) + + return response + + async def fetch_derivative_orders_by_hashes( + self, + market_id: str, + subaccount_id: str, + order_hashes: List[str], + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeOrdersByHashesRequest( + market_id=market_id, + subaccount_id=subaccount_id, + order_hashes=order_hashes, + ) + response = await self._execute_call(call=self._stub.DerivativeOrdersByHashes, request=request) + + return response + + async def fetch_trader_derivative_transient_orders( + self, + market_id: str, + subaccount_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderDerivativeOrdersRequest( + market_id=market_id, + subaccount_id=subaccount_id, + ) + response = await self._execute_call(call=self._stub.TraderDerivativeTransientOrders, request=request) + + return response + + async def fetch_derivative_markets( + self, + status: Optional[str] = None, + market_ids: Optional[List[str]] = None, + with_mid_price_and_tob: Optional[bool] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMarketsRequest( + status=status, + market_ids=market_ids, + with_mid_price_and_tob=with_mid_price_and_tob, + ) + response = await self._execute_call(call=self._stub.DerivativeMarkets, request=request) + + return response + + async def fetch_derivative_market( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMarketRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.DerivativeMarket, request=request) + + return response + + async def fetch_derivative_market_address( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryDerivativeMarketAddressRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.DerivativeMarketAddress, request=request) + + return response + + async def fetch_subaccount_trade_nonce(self, subaccount_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountTradeNonceRequest(subaccount_id=subaccount_id) + response = await self._execute_call(call=self._stub.SubaccountTradeNonce, request=request) + + return response + + async def fetch_positions(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryPositionsRequest() + response = await self._execute_call(call=self._stub.Positions, request=request) + + return response + + async def fetch_subaccount_positions(self, subaccount_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountPositionsRequest(subaccount_id=subaccount_id) + response = await self._execute_call(call=self._stub.SubaccountPositions, request=request) + + return response + + async def fetch_subaccount_position_in_market(self, subaccount_id: str, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountPositionInMarketRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SubaccountPositionInMarket, request=request) + + return response + + async def fetch_subaccount_effective_position_in_market(self, subaccount_id: str, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountEffectivePositionInMarketRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.SubaccountEffectivePositionInMarket, request=request) + + return response + + async def fetch_perpetual_market_info(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryPerpetualMarketInfoRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.PerpetualMarketInfo, request=request) + + return response + + async def fetch_expiry_futures_market_info(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryExpiryFuturesMarketInfoRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.ExpiryFuturesMarketInfo, request=request) + + return response + + async def fetch_perpetual_market_funding(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryPerpetualMarketFundingRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.PerpetualMarketFunding, request=request) + + return response + + async def fetch_subaccount_order_metadata(self, subaccount_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QuerySubaccountOrderMetadataRequest(subaccount_id=subaccount_id) + response = await self._execute_call(call=self._stub.SubaccountOrderMetadata, request=request) + + return response + + async def fetch_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTradeRewardPointsRequest( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + response = await self._execute_call(call=self._stub.TradeRewardPoints, request=request) + + return response + + async def fetch_pending_trade_reward_points( + self, + accounts: Optional[List[str]] = None, + pending_pool_timestamp: Optional[int] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTradeRewardPointsRequest( + accounts=accounts, + pending_pool_timestamp=pending_pool_timestamp, + ) + response = await self._execute_call(call=self._stub.PendingTradeRewardPoints, request=request) + + return response + + async def fetch_fee_discount_account_info( + self, + account: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryFeeDiscountAccountInfoRequest(account=account) + response = await self._execute_call(call=self._stub.FeeDiscountAccountInfo, request=request) + + return response + + async def fetch_fee_discount_schedule(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryFeeDiscountScheduleRequest() + response = await self._execute_call(call=self._stub.FeeDiscountSchedule, request=request) + + return response + + async def fetch_balance_mismatches(self, dust_factor: int) -> Dict[str, Any]: + request = exchange_query_pb.QueryBalanceMismatchesRequest(dust_factor=dust_factor) + response = await self._execute_call(call=self._stub.BalanceMismatches, request=request) + + return response + + async def fetch_balance_with_balance_holds(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryBalanceWithBalanceHoldsRequest() + response = await self._execute_call(call=self._stub.BalanceWithBalanceHolds, request=request) + + return response + + async def fetch_fee_discount_tier_statistics(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryFeeDiscountTierStatisticsRequest() + response = await self._execute_call(call=self._stub.FeeDiscountTierStatistics, request=request) + + return response + + async def fetch_mito_vault_infos(self) -> Dict[str, Any]: + request = exchange_query_pb.MitoVaultInfosRequest() + response = await self._execute_call(call=self._stub.MitoVaultInfos, request=request) + + return response + + async def fetch_market_id_from_vault(self, vault_address: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryMarketIDFromVaultRequest(vault_address=vault_address) + response = await self._execute_call(call=self._stub.QueryMarketIDFromVault, request=request) + + return response + + async def fetch_historical_trade_records(self, market_id: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryHistoricalTradeRecordsRequest(market_id=market_id) + response = await self._execute_call(call=self._stub.HistoricalTradeRecords, request=request) + + return response + + async def fetch_is_opted_out_of_rewards(self, account: str) -> Dict[str, Any]: + request = exchange_query_pb.QueryIsOptedOutOfRewardsRequest(account=account) + response = await self._execute_call(call=self._stub.IsOptedOutOfRewards, request=request) + + return response + + async def fetch_opted_out_of_rewards_accounts(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryOptedOutOfRewardsAccountsRequest() + response = await self._execute_call(call=self._stub.OptedOutOfRewardsAccounts, request=request) + + return response + + async def fetch_market_volatility( + self, + market_id: str, + trade_grouping_sec: Optional[int] = None, + max_age: Optional[int] = None, + include_raw_history: Optional[bool] = None, + include_metadata: Optional[bool] = None, + ) -> Dict[str, Any]: + trade_history_options = exchange_query_pb.TradeHistoryOptions() + if trade_grouping_sec is not None: + trade_history_options.trade_grouping_sec = trade_grouping_sec + if max_age is not None: + trade_history_options.max_age = max_age + if include_raw_history is not None: + trade_history_options.include_raw_history = include_raw_history + if include_metadata is not None: + trade_history_options.include_metadata = include_metadata + request = exchange_query_pb.QueryMarketVolatilityRequest( + market_id=market_id, trade_history_options=trade_history_options + ) + response = await self._execute_call(call=self._stub.MarketVolatility, request=request) + + return response + + async def fetch_binary_options_markets(self, status: Optional[str] = None) -> Dict[str, Any]: + request = exchange_query_pb.QueryBinaryMarketsRequest(status=status) + response = await self._execute_call(call=self._stub.BinaryOptionsMarkets, request=request) + + return response + + async def fetch_trader_derivative_conditional_orders( + self, + subaccount_id: Optional[str] = None, + market_id: Optional[str] = None, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryTraderDerivativeConditionalOrdersRequest( + subaccount_id=subaccount_id, + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.TraderDerivativeConditionalOrders, request=request) + + return response + + async def fetch_market_atomic_execution_fee_multiplier( + self, + market_id: str, + ) -> Dict[str, Any]: + request = exchange_query_pb.QueryMarketAtomicExecutionFeeMultiplierRequest( + market_id=market_id, + ) + response = await self._execute_call(call=self._stub.MarketAtomicExecutionFeeMultiplier, request=request) + + return response + + async def _execute_call(self, call: Callable, request) -> Dict[str, Any]: + return await self._assistant.execute_call(call=call, request=request) diff --git a/tests/client/chain/grpc/configurable_exchange_query_servicer.py b/tests/client/chain/grpc/configurable_exchange_query_servicer.py new file mode 100644 index 00000000..267b08ce --- /dev/null +++ b/tests/client/chain/grpc/configurable_exchange_query_servicer.py @@ -0,0 +1,325 @@ +from collections import deque + +from pyinjective.proto.injective.exchange.v1beta1 import ( + query_pb2 as exchange_query_pb, + query_pb2_grpc as exchange_query_grpc, +) + + +class ConfigurableExchangeQueryServicer(exchange_query_grpc.QueryServicer): + def __init__(self): + super().__init__() + self.exchange_params = deque() + self.subaccount_deposits_responses = deque() + self.subaccount_deposit_responses = deque() + self.exchange_balances_responses = deque() + self.aggregate_volume_responses = deque() + self.aggregate_volumes_responses = deque() + self.aggregate_market_volume_responses = deque() + self.aggregate_market_volumes_responses = deque() + self.denom_decimal_responses = deque() + self.denom_decimals_responses = deque() + self.spot_markets_responses = deque() + self.spot_market_responses = deque() + self.full_spot_markets_responses = deque() + self.full_spot_market_responses = deque() + self.spot_orderbook_responses = deque() + self.trader_spot_orders_responses = deque() + self.account_address_spot_orders_responses = deque() + self.spot_orders_by_hashes_responses = deque() + self.subaccount_orders_responses = deque() + self.trader_spot_transient_orders_responses = deque() + self.spot_mid_price_and_tob_responses = deque() + self.derivative_mid_price_and_tob_responses = deque() + self.derivative_orderbook_responses = deque() + self.trader_derivative_orders_responses = deque() + self.account_address_derivative_orders_responses = deque() + self.derivative_orders_by_hashes_responses = deque() + self.trader_derivative_transient_orders_responses = deque() + self.derivative_markets_responses = deque() + self.derivative_market_responses = deque() + self.derivative_market_address_responses = deque() + self.subaccount_trade_nonce_responses = deque() + self.positions_responses = deque() + self.subaccount_positions_responses = deque() + self.subaccount_position_in_market_responses = deque() + self.subaccount_effective_position_in_market_responses = deque() + self.perpetual_market_info_responses = deque() + self.expiry_futures_market_info_responses = deque() + self.perpetual_market_funding_responses = deque() + self.subaccount_order_metadata_responses = deque() + self.trade_reward_points_responses = deque() + self.pending_trade_reward_points_responses = deque() + self.fee_discount_account_info_responses = deque() + self.fee_discount_schedule_responses = deque() + self.balance_mismatches_responses = deque() + self.balance_with_balance_holds_responses = deque() + self.fee_discount_tier_statistics_responses = deque() + self.mito_vault_infos_responses = deque() + self.market_id_from_vault_responses = deque() + self.historical_trade_records_responses = deque() + self.is_opted_out_of_rewards_responses = deque() + self.opted_out_of_rewards_accounts_responses = deque() + self.market_volatility_responses = deque() + self.binary_options_markets_responses = deque() + self.trader_derivative_conditional_orders_responses = deque() + self.market_atomic_execution_fee_multiplier_responses = deque() + + async def QueryExchangeParams( + self, request: exchange_query_pb.QueryExchangeParamsRequest, context=None, metadata=None + ): + return self.exchange_params.pop() + + async def SubaccountDeposits( + self, request: exchange_query_pb.QuerySubaccountDepositsRequest, context=None, metadata=None + ): + return self.subaccount_deposits_responses.pop() + + async def SubaccountDeposit( + self, request: exchange_query_pb.QuerySubaccountDepositRequest, context=None, metadata=None + ): + return self.subaccount_deposit_responses.pop() + + async def ExchangeBalances( + self, request: exchange_query_pb.QueryExchangeBalancesRequest, context=None, metadata=None + ): + return self.exchange_balances_responses.pop() + + async def AggregateVolume( + self, request: exchange_query_pb.QueryAggregateVolumeRequest, context=None, metadata=None + ): + return self.aggregate_volume_responses.pop() + + async def AggregateVolumes( + self, request: exchange_query_pb.QueryAggregateVolumesRequest, context=None, metadata=None + ): + return self.aggregate_volumes_responses.pop() + + async def AggregateMarketVolume( + self, request: exchange_query_pb.QueryAggregateMarketVolumeRequest, context=None, metadata=None + ): + return self.aggregate_market_volume_responses.pop() + + async def AggregateMarketVolumes( + self, request: exchange_query_pb.QueryAggregateMarketVolumesRequest, context=None, metadata=None + ): + return self.aggregate_market_volumes_responses.pop() + + async def DenomDecimal(self, request: exchange_query_pb.QueryDenomDecimalRequest, context=None, metadata=None): + return self.denom_decimal_responses.pop() + + async def DenomDecimals(self, request: exchange_query_pb.QueryDenomDecimalsRequest, context=None, metadata=None): + return self.denom_decimals_responses.pop() + + async def SpotMarkets(self, request: exchange_query_pb.QuerySpotMarketsRequest, context=None, metadata=None): + return self.spot_markets_responses.pop() + + async def SpotMarket(self, request: exchange_query_pb.QuerySpotMarketRequest, context=None, metadata=None): + return self.spot_market_responses.pop() + + async def FullSpotMarkets( + self, request: exchange_query_pb.QueryFullSpotMarketsRequest, context=None, metadata=None + ): + return self.full_spot_markets_responses.pop() + + async def FullSpotMarket(self, request: exchange_query_pb.QueryFullSpotMarketRequest, context=None, metadata=None): + return self.full_spot_market_responses.pop() + + async def SpotOrderbook(self, request: exchange_query_pb.QuerySpotOrderbookRequest, context=None, metadata=None): + return self.spot_orderbook_responses.pop() + + async def TraderSpotOrders( + self, request: exchange_query_pb.QueryTraderSpotOrdersRequest, context=None, metadata=None + ): + return self.trader_spot_orders_responses.pop() + + async def AccountAddressSpotOrders( + self, request: exchange_query_pb.QueryAccountAddressSpotOrdersRequest, context=None, metadata=None + ): + return self.account_address_spot_orders_responses.pop() + + async def SpotOrdersByHashes( + self, request: exchange_query_pb.QuerySpotOrdersByHashesRequest, context=None, metadata=None + ): + return self.spot_orders_by_hashes_responses.pop() + + async def SubaccountOrders( + self, request: exchange_query_pb.QuerySubaccountOrdersRequest, context=None, metadata=None + ): + return self.subaccount_orders_responses.pop() + + async def TraderSpotTransientOrders( + self, request: exchange_query_pb.QueryTraderSpotOrdersRequest, context=None, metadata=None + ): + return self.trader_spot_transient_orders_responses.pop() + + async def SpotMidPriceAndTOB( + self, request: exchange_query_pb.QuerySpotMidPriceAndTOBRequest, context=None, metadata=None + ): + return self.spot_mid_price_and_tob_responses.pop() + + async def DerivativeMidPriceAndTOB( + self, request: exchange_query_pb.QueryDerivativeMidPriceAndTOBRequest, context=None, metadata=None + ): + return self.derivative_mid_price_and_tob_responses.pop() + + async def DerivativeOrderbook( + self, request: exchange_query_pb.QueryDerivativeOrderbookRequest, context=None, metadata=None + ): + return self.derivative_orderbook_responses.pop() + + async def TraderDerivativeOrders( + self, request: exchange_query_pb.QueryTraderDerivativeOrdersRequest, context=None, metadata=None + ): + return self.trader_derivative_orders_responses.pop() + + async def AccountAddressDerivativeOrders( + self, request: exchange_query_pb.QueryAccountAddressDerivativeOrdersRequest, context=None, metadata=None + ): + return self.account_address_derivative_orders_responses.pop() + + async def DerivativeOrdersByHashes( + self, request: exchange_query_pb.QueryDerivativeOrdersByHashesRequest, context=None, metadata=None + ): + return self.derivative_orders_by_hashes_responses.pop() + + async def TraderDerivativeTransientOrders( + self, request: exchange_query_pb.QueryTraderDerivativeOrdersRequest, context=None, metadata=None + ): + return self.trader_derivative_transient_orders_responses.pop() + + async def DerivativeMarkets( + self, request: exchange_query_pb.QueryDerivativeMarketsRequest, context=None, metadata=None + ): + return self.derivative_markets_responses.pop() + + async def DerivativeMarket( + self, request: exchange_query_pb.QueryDerivativeMarketRequest, context=None, metadata=None + ): + return self.derivative_market_responses.pop() + + async def DerivativeMarketAddress( + self, request: exchange_query_pb.QueryDerivativeMarketAddressRequest, context=None, metadata=None + ): + return self.derivative_market_address_responses.pop() + + async def SubaccountTradeNonce( + self, request: exchange_query_pb.QuerySubaccountTradeNonceRequest, context=None, metadata=None + ): + return self.subaccount_trade_nonce_responses.pop() + + async def Positions(self, request: exchange_query_pb.QueryPositionsRequest, context=None, metadata=None): + return self.positions_responses.pop() + + async def SubaccountPositions( + self, request: exchange_query_pb.QuerySubaccountPositionsRequest, context=None, metadata=None + ): + return self.subaccount_positions_responses.pop() + + async def SubaccountPositionInMarket( + self, request: exchange_query_pb.QuerySubaccountPositionInMarketRequest, context=None, metadata=None + ): + return self.subaccount_position_in_market_responses.pop() + + async def SubaccountEffectivePositionInMarket( + self, request: exchange_query_pb.QuerySubaccountEffectivePositionInMarketRequest, context=None, metadata=None + ): + return self.subaccount_effective_position_in_market_responses.pop() + + async def PerpetualMarketInfo( + self, request: exchange_query_pb.QueryPerpetualMarketInfoRequest, context=None, metadata=None + ): + return self.perpetual_market_info_responses.pop() + + async def ExpiryFuturesMarketInfo( + self, request: exchange_query_pb.QueryExpiryFuturesMarketInfoRequest, context=None, metadata=None + ): + return self.expiry_futures_market_info_responses.pop() + + async def PerpetualMarketFunding( + self, request: exchange_query_pb.QueryPerpetualMarketFundingRequest, context=None, metadata=None + ): + return self.perpetual_market_funding_responses.pop() + + async def SubaccountOrderMetadata( + self, request: exchange_query_pb.QuerySubaccountOrderMetadataRequest, context=None, metadata=None + ): + return self.subaccount_order_metadata_responses.pop() + + async def TradeRewardPoints( + self, request: exchange_query_pb.QueryTradeRewardPointsRequest, context=None, metadata=None + ): + return self.trade_reward_points_responses.pop() + + async def PendingTradeRewardPoints( + self, request: exchange_query_pb.QueryTradeRewardPointsRequest, context=None, metadata=None + ): + return self.pending_trade_reward_points_responses.pop() + + async def FeeDiscountAccountInfo( + self, request: exchange_query_pb.QueryFeeDiscountAccountInfoRequest, context=None, metadata=None + ): + return self.fee_discount_account_info_responses.pop() + + async def FeeDiscountSchedule( + self, request: exchange_query_pb.QueryFeeDiscountScheduleRequest, context=None, metadata=None + ): + return self.fee_discount_schedule_responses.pop() + + async def BalanceMismatches( + self, request: exchange_query_pb.QueryBalanceMismatchesRequest, context=None, metadata=None + ): + return self.balance_mismatches_responses.pop() + + async def BalanceWithBalanceHolds( + self, request: exchange_query_pb.QueryBalanceWithBalanceHoldsRequest, context=None, metadata=None + ): + return self.balance_with_balance_holds_responses.pop() + + async def FeeDiscountTierStatistics( + self, request: exchange_query_pb.QueryFeeDiscountTierStatisticsRequest, context=None, metadata=None + ): + return self.fee_discount_tier_statistics_responses.pop() + + async def MitoVaultInfos(self, request: exchange_query_pb.MitoVaultInfosRequest, context=None, metadata=None): + return self.mito_vault_infos_responses.pop() + + async def QueryMarketIDFromVault( + self, request: exchange_query_pb.QueryMarketIDFromVaultRequest, context=None, metadata=None + ): + return self.market_id_from_vault_responses.pop() + + async def HistoricalTradeRecords( + self, request: exchange_query_pb.QueryHistoricalTradeRecordsRequest, context=None, metadata=None + ): + return self.historical_trade_records_responses.pop() + + async def IsOptedOutOfRewards( + self, request: exchange_query_pb.QueryIsOptedOutOfRewardsRequest, context=None, metadata=None + ): + return self.is_opted_out_of_rewards_responses.pop() + + async def OptedOutOfRewardsAccounts( + self, request: exchange_query_pb.QueryOptedOutOfRewardsAccountsRequest, context=None, metadata=None + ): + return self.opted_out_of_rewards_accounts_responses.pop() + + async def MarketVolatility( + self, request: exchange_query_pb.QueryMarketVolatilityRequest, context=None, metadata=None + ): + return self.market_volatility_responses.pop() + + async def BinaryOptionsMarkets( + self, request: exchange_query_pb.QueryBinaryMarketsRequest, context=None, metadata=None + ): + return self.binary_options_markets_responses.pop() + + async def TraderDerivativeConditionalOrders( + self, request: exchange_query_pb.QueryTraderDerivativeConditionalOrdersRequest, context=None, metadata=None + ): + return self.trader_derivative_conditional_orders_responses.pop() + + async def MarketAtomicExecutionFeeMultiplier( + self, request: exchange_query_pb.QueryMarketAtomicExecutionFeeMultiplierRequest, context=None, metadata=None + ): + return self.market_atomic_execution_fee_multiplier_responses.pop() diff --git a/tests/client/chain/grpc/test_chain_grpc_exchange_api.py b/tests/client/chain/grpc/test_chain_grpc_exchange_api.py new file mode 100644 index 00000000..54393a94 --- /dev/null +++ b/tests/client/chain/grpc/test_chain_grpc_exchange_api.py @@ -0,0 +1,2466 @@ +import base64 + +import grpc +import pytest + +from pyinjective.client.chain.grpc.chain_grpc_exchange_api import ChainGrpcExchangeApi +from pyinjective.client.model.pagination import PaginationOption +from pyinjective.core.network import Network +from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as coin_pb +from pyinjective.proto.injective.exchange.v1beta1 import ( + exchange_pb2 as exchange_pb, + genesis_pb2 as genesis_pb, + query_pb2 as exchange_query_pb, +) +from pyinjective.proto.injective.oracle.v1beta1 import oracle_pb2 as oracle_pb +from tests.client.chain.grpc.configurable_exchange_query_servicer import ConfigurableExchangeQueryServicer + + +@pytest.fixture +def exchange_servicer(): + return ConfigurableExchangeQueryServicer() + + +class TestChainGrpcBankApi: + @pytest.mark.asyncio + async def test_fetch_exchange_params( + self, + exchange_servicer, + ): + spot_market_instant_listing_fee = coin_pb.Coin(denom="inj", amount="10000000000000000000") + derivative_market_instant_listing_fee = coin_pb.Coin(denom="inj", amount="2000000000000000000000") + binary_options_market_instant_listing_fee = coin_pb.Coin(denom="inj", amount="30000000000000000000") + params = exchange_pb.Params( + spot_market_instant_listing_fee=spot_market_instant_listing_fee, + derivative_market_instant_listing_fee=derivative_market_instant_listing_fee, + default_spot_maker_fee_rate="-0.000100000000000000", + default_spot_taker_fee_rate="0.001000000000000000", + default_derivative_maker_fee_rate="-0.000100000000000000", + default_derivative_taker_fee_rate="0.001000000000000000", + default_initial_margin_ratio="0.050000000000000000", + default_maintenance_margin_ratio="0.020000000000000000", + default_funding_interval=3600, + funding_multiple=4600, + relayer_fee_share_rate="0.400000000000000000", + default_hourly_funding_rate_cap="0.000625000000000000", + default_hourly_interest_rate="0.000004166660000000", + max_derivative_order_side_count=20, + inj_reward_staked_requirement_threshold="25000000000000000000", + trading_rewards_vesting_duration=1209600, + liquidator_reward_share_rate="0.050000000000000000", + binary_options_market_instant_listing_fee=binary_options_market_instant_listing_fee, + atomic_market_order_access_level=2, + spot_atomic_market_order_fee_multiplier="2.000000000000000000", + derivative_atomic_market_order_fee_multiplier="2.000000000000000000", + binary_options_atomic_market_order_fee_multiplier="2.000000000000000000", + minimal_protocol_fee_rate="0.000010000000000000", + is_instant_derivative_market_launch_enabled=False, + post_only_mode_height_threshold=57078000, + ) + exchange_servicer.exchange_params.append(exchange_query_pb.QueryExchangeParamsResponse(params=params)) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + module_params = await api.fetch_exchange_params() + expected_params = { + "params": { + "spotMarketInstantListingFee": { + "amount": spot_market_instant_listing_fee.amount, + "denom": spot_market_instant_listing_fee.denom, + }, + "derivativeMarketInstantListingFee": { + "amount": derivative_market_instant_listing_fee.amount, + "denom": derivative_market_instant_listing_fee.denom, + }, + "defaultSpotMakerFeeRate": params.default_spot_maker_fee_rate, + "defaultSpotTakerFeeRate": params.default_spot_taker_fee_rate, + "defaultDerivativeMakerFeeRate": params.default_derivative_maker_fee_rate, + "defaultDerivativeTakerFeeRate": params.default_derivative_taker_fee_rate, + "defaultInitialMarginRatio": params.default_initial_margin_ratio, + "defaultMaintenanceMarginRatio": params.default_maintenance_margin_ratio, + "defaultFundingInterval": str(params.default_funding_interval), + "fundingMultiple": str(params.funding_multiple), + "relayerFeeShareRate": params.relayer_fee_share_rate, + "defaultHourlyFundingRateCap": params.default_hourly_funding_rate_cap, + "defaultHourlyInterestRate": params.default_hourly_interest_rate, + "maxDerivativeOrderSideCount": params.max_derivative_order_side_count, + "injRewardStakedRequirementThreshold": params.inj_reward_staked_requirement_threshold, + "tradingRewardsVestingDuration": str(params.trading_rewards_vesting_duration), + "liquidatorRewardShareRate": "0.050000000000000000", + "binaryOptionsMarketInstantListingFee": { + "amount": binary_options_market_instant_listing_fee.amount, + "denom": binary_options_market_instant_listing_fee.denom, + }, + "atomicMarketOrderAccessLevel": exchange_pb.AtomicMarketOrderAccessLevel.Name( + params.atomic_market_order_access_level + ), + "spotAtomicMarketOrderFeeMultiplier": params.spot_atomic_market_order_fee_multiplier, + "derivativeAtomicMarketOrderFeeMultiplier": params.derivative_atomic_market_order_fee_multiplier, + "binaryOptionsAtomicMarketOrderFeeMultiplier": params.binary_options_atomic_market_order_fee_multiplier, + "minimalProtocolFeeRate": params.minimal_protocol_fee_rate, + "isInstantDerivativeMarketLaunchEnabled": params.is_instant_derivative_market_launch_enabled, + "postOnlyModeHeightThreshold": str(params.post_only_mode_height_threshold), + } + } + + assert module_params == expected_params + + @pytest.mark.asyncio + async def test_fetch_subaccount_deposits( + self, + exchange_servicer, + ): + deposit_denom = "inj" + deposit = exchange_pb.Deposit( + available_balance="1000000000000000000", + total_balance="2000000000000000000", + ) + exchange_servicer.subaccount_deposits_responses.append( + exchange_query_pb.QuerySubaccountDepositsResponse(deposits={deposit_denom: deposit}) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + deposits = await api.fetch_subaccount_deposits( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + subaccount_trader="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7", + subaccount_nonce=1, + ) + expected_deposits = { + "deposits": { + deposit_denom: { + "availableBalance": deposit.available_balance, + "totalBalance": deposit.total_balance, + }, + } + } + + assert deposits == expected_deposits + + @pytest.mark.asyncio + async def test_fetch_subaccount_deposit( + self, + exchange_servicer, + ): + deposit = exchange_pb.Deposit( + available_balance="1000000000000000000", + total_balance="2000000000000000000", + ) + exchange_servicer.subaccount_deposit_responses.append( + exchange_query_pb.QuerySubaccountDepositResponse(deposits=deposit) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + deposit_response = await api.fetch_subaccount_deposit( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="inj", + ) + expected_deposit = { + "deposits": { + "availableBalance": deposit.available_balance, + "totalBalance": deposit.total_balance, + } + } + + assert deposit_response == expected_deposit + + @pytest.mark.asyncio + async def test_fetch_exchange_balances( + self, + exchange_servicer, + ): + deposit = exchange_pb.Deposit( + available_balance="1000000000000000000", + total_balance="2000000000000000000", + ) + balance = genesis_pb.Balance( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="inj", + deposits=deposit, + ) + exchange_servicer.exchange_balances_responses.append( + exchange_query_pb.QueryExchangeBalancesResponse(balances=[balance]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + balances_response = await api.fetch_exchange_balances() + expected_balances = { + "balances": [ + { + "subaccountId": balance.subaccount_id, + "denom": balance.denom, + "deposits": { + "availableBalance": deposit.available_balance, + "totalBalance": deposit.total_balance, + }, + }, + ] + } + + assert balances_response == expected_balances + + @pytest.mark.asyncio + async def test_fetch_aggregate_volume( + self, + exchange_servicer, + ): + volume = exchange_pb.VolumeRecord( + maker_volume="1000000000000000000", + taker_volume="2000000000000000000", + ) + market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=volume, + ) + exchange_servicer.aggregate_volume_responses.append( + exchange_query_pb.QueryAggregateVolumeResponse( + aggregate_volumes=[market_volume], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_volume(account="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r") + expected_volume = { + "aggregateVolumes": [ + { + "marketId": market_volume.market_id, + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + }, + }, + ] + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_aggregate_volumes( + self, + exchange_servicer, + ): + acc_volume = exchange_pb.VolumeRecord( + maker_volume="1000000000000000000", + taker_volume="2000000000000000000", + ) + account_market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=acc_volume, + ) + account_volume = exchange_pb.AggregateAccountVolumeRecord( + account="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + market_volumes=[account_market_volume], + ) + volume = exchange_pb.VolumeRecord( + maker_volume="3000000000000000000", + taker_volume="4000000000000000000", + ) + market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=volume, + ) + exchange_servicer.aggregate_volumes_responses.append( + exchange_query_pb.QueryAggregateVolumesResponse( + aggregate_account_volumes=[account_volume], + aggregate_market_volumes=[market_volume], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_volumes( + accounts=[account_volume.account], + market_ids=[account_market_volume.market_id], + ) + expected_volume = { + "aggregateAccountVolumes": [ + { + "account": account_volume.account, + "marketVolumes": [ + { + "marketId": account_market_volume.market_id, + "volume": { + "makerVolume": acc_volume.maker_volume, + "takerVolume": acc_volume.taker_volume, + }, + }, + ], + }, + ], + "aggregateMarketVolumes": [ + { + "marketId": market_volume.market_id, + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + }, + }, + ], + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_aggregate_market_volume( + self, + exchange_servicer, + ): + volume = exchange_pb.VolumeRecord( + maker_volume="1000000000000000000", + taker_volume="2000000000000000000", + ) + exchange_servicer.aggregate_market_volume_responses.append( + exchange_query_pb.QueryAggregateMarketVolumeResponse( + volume=volume, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_market_volume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" + ) + expected_volume = { + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + } + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_aggregate_market_volumes( + self, + exchange_servicer, + ): + volume = exchange_pb.VolumeRecord( + maker_volume="3000000000000000000", + taker_volume="4000000000000000000", + ) + market_volume = exchange_pb.MarketVolume( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + volume=volume, + ) + exchange_servicer.aggregate_market_volumes_responses.append( + exchange_query_pb.QueryAggregateMarketVolumesResponse( + volumes=[market_volume], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volume_response = await api.fetch_aggregate_market_volumes( + market_ids=[market_volume.market_id], + ) + expected_volume = { + "volumes": [ + { + "marketId": market_volume.market_id, + "volume": { + "makerVolume": volume.maker_volume, + "takerVolume": volume.taker_volume, + }, + }, + ], + } + + assert volume_response == expected_volume + + @pytest.mark.asyncio + async def test_fetch_denom_decimal( + self, + exchange_servicer, + ): + decimal = 18 + exchange_servicer.denom_decimal_responses.append( + exchange_query_pb.QueryDenomDecimalResponse( + decimal=decimal, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + denom_decimal = await api.fetch_denom_decimal(denom="inj") + expected_decimal = {"decimal": str(decimal)} + + assert denom_decimal == expected_decimal + + @pytest.mark.asyncio + async def test_fetch_denom_decimals( + self, + exchange_servicer, + ): + denom_decimal = exchange_pb.DenomDecimals( + denom="inj", + decimals=18, + ) + exchange_servicer.denom_decimals_responses.append( + exchange_query_pb.QueryDenomDecimalsResponse( + denom_decimals=[denom_decimal], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + denom_decimals = await api.fetch_denom_decimals(denoms=[denom_decimal.denom]) + expected_decimals = { + "denomDecimals": [ + { + "denom": denom_decimal.denom, + "decimals": str(denom_decimal.decimals), + } + ] + } + + assert denom_decimals == expected_decimals + + @pytest.mark.asyncio + async def test_fetch_spot_markets( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + exchange_servicer.spot_markets_responses.append( + exchange_query_pb.QuerySpotMarketsResponse( + markets=[market], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + markets = await api.fetch_spot_markets( + status=status_string, + market_ids=[market.market_id], + ) + expected_markets = { + "markets": [ + { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + } + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_spot_market( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + exchange_servicer.spot_market_responses.append( + exchange_query_pb.QuerySpotMarketResponse( + market=market, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + response_market = await api.fetch_spot_market( + market_id=market.market_id, + ) + expected_market = { + "market": { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": exchange_pb.MarketStatus.Name(market.status), + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + } + } + + assert response_market == expected_market + + @pytest.mark.asyncio + async def test_fetch_full_spot_markets( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullSpotMarket( + market=market, + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.full_spot_markets_responses.append( + exchange_query_pb.QueryFullSpotMarketsResponse( + markets=[full_market], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + markets = await api.fetch_full_spot_markets( + status=status_string, + market_ids=[market.market_id], + with_mid_price_and_tob=True, + ) + expected_markets = { + "markets": [ + { + "market": { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_full_spot_market( + self, + exchange_servicer, + ): + market = exchange_pb.SpotMarket( + ticker="INJ/USDT", + base_denom="inj", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="0.4", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + status=1, + min_price_tick_size="0.000000000000001", + min_quantity_tick_size="1000000000000000", + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullSpotMarket( + market=market, + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.full_spot_market_responses.append( + exchange_query_pb.QueryFullSpotMarketResponse( + market=full_market, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + market_response = await api.fetch_full_spot_market( + market_id=market.market_id, + with_mid_price_and_tob=True, + ) + expected_market = { + "market": { + "market": { + "ticker": market.ticker, + "baseDenom": market.base_denom, + "quoteDenom": market.quote_denom, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "marketId": market.market_id, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + } + + assert market_response == expected_market + + @pytest.mark.asyncio + async def test_fetch_spot_orderbook( + self, + exchange_servicer, + ): + buy_price_level = exchange_pb.Level( + p="1000000000000000000", + q="1000000000000000", + ) + sell_price_level = exchange_pb.Level( + p="2000000000000000000", + q="2000000000000000", + ) + exchange_servicer.spot_orderbook_responses.append( + exchange_query_pb.QuerySpotOrderbookResponse( + buys_price_level=[buy_price_level], + sells_price_level=[sell_price_level], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orderbook = await api.fetch_spot_orderbook( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + order_side="Side_Unspecified", + limit_cumulative_notional="1000000000000000000", + limit_cumulative_quantity="1000000000000000", + pagination=PaginationOption(limit=100), + ) + expected_orderbook = { + "buysPriceLevel": [ + { + "p": buy_price_level.p, + "q": buy_price_level.q, + } + ], + "sellsPriceLevel": [ + { + "p": sell_price_level.p, + "q": sell_price_level.q, + } + ], + } + + assert orderbook == expected_orderbook + + @pytest.mark.asyncio + async def test_fetch_trader_spot_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_spot_orders_responses.append( + exchange_query_pb.QueryTraderSpotOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_account_address_spot_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.account_address_spot_orders_responses.append( + exchange_query_pb.QueryAccountAddressSpotOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_account_address_spot_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + account_address="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_spot_orders_by_hashes( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.spot_orders_by_hashes_responses.append( + exchange_query_pb.QuerySpotOrdersByHashesResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_spot_orders_by_hashes( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + order_hashes=[order.order_hash], + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_subaccount_orders( + self, + exchange_servicer, + ): + buy_subaccount_order = exchange_pb.SubaccountOrder( + price="1000000000000000000", + quantity="1000000000000000", + isReduceOnly=False, + ) + buy_order = exchange_pb.SubaccountOrderData( + order=buy_subaccount_order, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849".encode(), + ) + sell_subaccount_order = exchange_pb.SubaccountOrder( + price="2000000000000000000", + quantity="2000000000000000", + isReduceOnly=False, + ) + sell_order = exchange_pb.SubaccountOrderData( + order=sell_subaccount_order, + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2".encode(), + ) + exchange_servicer.subaccount_orders_responses.append( + exchange_query_pb.QuerySubaccountOrdersResponse( + buy_orders=[buy_order], + sell_orders=[sell_order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_subaccount_orders( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + expected_orders = { + "buyOrders": [ + { + "order": { + "price": buy_subaccount_order.price, + "quantity": buy_subaccount_order.quantity, + "isReduceOnly": buy_subaccount_order.isReduceOnly, + }, + "orderHash": base64.b64encode(buy_order.order_hash).decode(), + } + ], + "sellOrders": [ + { + "order": { + "price": sell_subaccount_order.price, + "quantity": sell_subaccount_order.quantity, + "isReduceOnly": sell_subaccount_order.isReduceOnly, + }, + "orderHash": base64.b64encode(sell_order.order_hash).decode(), + } + ], + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_trader_spot_transient_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedSpotLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_spot_transient_orders_responses.append( + exchange_query_pb.QueryTraderSpotOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_spot_transient_orders( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_spot_mid_price_and_tob( + self, + exchange_servicer, + ): + response = exchange_query_pb.QuerySpotMidPriceAndTOBResponse( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + exchange_servicer.spot_mid_price_and_tob_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + prices = await api.fetch_spot_mid_price_and_tob( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + expected_prices = { + "midPrice": response.mid_price, + "bestBuyPrice": response.best_buy_price, + "bestSellPrice": response.best_sell_price, + } + + assert prices == expected_prices + + @pytest.mark.asyncio + async def test_fetch_derivative_mid_price_and_tob( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryDerivativeMidPriceAndTOBResponse( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + exchange_servicer.derivative_mid_price_and_tob_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + prices = await api.fetch_derivative_mid_price_and_tob( + market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", + ) + expected_prices = { + "midPrice": response.mid_price, + "bestBuyPrice": response.best_buy_price, + "bestSellPrice": response.best_sell_price, + } + + assert prices == expected_prices + + @pytest.mark.asyncio + async def test_fetch_derivative_orderbook( + self, + exchange_servicer, + ): + buy_price_level = exchange_pb.Level( + p="1000000000000000000", + q="1000000000000000", + ) + sell_price_level = exchange_pb.Level( + p="2000000000000000000", + q="2000000000000000", + ) + exchange_servicer.derivative_orderbook_responses.append( + exchange_query_pb.QueryDerivativeOrderbookResponse( + buys_price_level=[buy_price_level], + sells_price_level=[sell_price_level], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orderbook = await api.fetch_derivative_orderbook( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + limit_cumulative_notional="1000000000000000000", + pagination=PaginationOption(limit=100), + ) + expected_orderbook = { + "buysPriceLevel": [ + { + "p": buy_price_level.p, + "q": buy_price_level.q, + } + ], + "sellsPriceLevel": [ + { + "p": sell_price_level.p, + "q": sell_price_level.q, + } + ], + } + + assert orderbook == expected_orderbook + + @pytest.mark.asyncio + async def test_fetch_trader_derivative_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_derivative_orders_responses.append( + exchange_query_pb.QueryTraderDerivativeOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_derivative_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_account_address_derivative_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.account_address_derivative_orders_responses.append( + exchange_query_pb.QueryAccountAddressDerivativeOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_account_address_derivative_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + account_address="inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_derivative_orders_by_hashes( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.derivative_orders_by_hashes_responses.append( + exchange_query_pb.QueryDerivativeOrdersByHashesResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_derivative_orders_by_hashes( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + order_hashes=[order.order_hash], + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_trader_derivative_transient_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeLimitOrder( + price="1000000000000000000", + quantity="1000000000000000", + margin="1000000000000000000000000000000000", + fillable="1000000000000000", + isBuy=True, + order_hash="0x14e43adbb3302db28bcd0619068227ebca880cdd66cdfc8b4a662bcac0777849", + ) + exchange_servicer.trader_derivative_transient_orders_responses.append( + exchange_query_pb.QueryTraderDerivativeOrdersResponse( + orders=[order], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_derivative_transient_orders( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "fillable": order.fillable, + "isBuy": order.isBuy, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_derivative_markets( + self, + exchange_servicer, + ): + market = exchange_pb.DerivativeMarket( + ticker="20250608/USDT", + oracle_base="0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3", + oracle_quote="0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588", + oracle_type=9, + oracle_scale_factor=6, + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + initial_margin_ratio="50000000000000000", + maintenance_margin_ratio="20000000000000000", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="400000000000000000", + isPerpetual=True, + status=1, + min_price_tick_size="100000000000000000000", + min_quantity_tick_size="1000000000000000", + ) + market_info = exchange_pb.PerpetualMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + hourly_funding_rate_cap="625000000000000", + hourly_interest_rate="4166660000000", + next_funding_timestamp=1708099200, + funding_interval=3600, + ) + funding_info = exchange_pb.PerpetualMarketFunding( + cumulative_funding="-107853477278881692857461", + cumulative_price="0", + last_timestamp=1708099200, + ) + perpetual_info = exchange_query_pb.PerpetualMarketState( + market_info=market_info, + funding_info=funding_info, + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullDerivativeMarket( + market=market, + perpetual_info=perpetual_info, + mark_price="33803835513327368963000000", + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.derivative_markets_responses.append( + exchange_query_pb.QueryDerivativeMarketsResponse( + markets=[full_market], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + markets = await api.fetch_derivative_markets( + status=status_string, + market_ids=[market.market_id], + ) + expected_markets = { + "markets": [ + { + "market": { + "ticker": market.ticker, + "oracleBase": market.oracle_base, + "oracleQuote": market.oracle_quote, + "oracleType": oracle_pb.OracleType.Name(market.oracle_type), + "oracleScaleFactor": market.oracle_scale_factor, + "quoteDenom": market.quote_denom, + "marketId": market.market_id, + "initialMarginRatio": market.initial_margin_ratio, + "maintenanceMarginRatio": market.maintenance_margin_ratio, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "isPerpetual": market.isPerpetual, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "perpetualInfo": { + "marketInfo": { + "marketId": market_info.market_id, + "hourlyFundingRateCap": market_info.hourly_funding_rate_cap, + "hourlyInterestRate": market_info.hourly_interest_rate, + "nextFundingTimestamp": str(market_info.next_funding_timestamp), + "fundingInterval": str(market_info.funding_interval), + }, + "fundingInfo": { + "cumulativeFunding": funding_info.cumulative_funding, + "cumulativePrice": funding_info.cumulative_price, + "lastTimestamp": str(funding_info.last_timestamp), + }, + }, + "markPrice": full_market.mark_price, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_derivative_market( + self, + exchange_servicer, + ): + market = exchange_pb.DerivativeMarket( + ticker="INJ/USDT PERP", + oracle_base="0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3", + oracle_quote="0x1fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c1588", + oracle_type=9, + oracle_scale_factor=6, + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + initial_margin_ratio="50000000000000000", + maintenance_margin_ratio="20000000000000000", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="400000000000000000", + isPerpetual=True, + status=1, + min_price_tick_size="100000000000000000000", + min_quantity_tick_size="1000000000000000", + ) + market_info = exchange_pb.PerpetualMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + hourly_funding_rate_cap="625000000000000", + hourly_interest_rate="4166660000000", + next_funding_timestamp=1708099200, + funding_interval=3600, + ) + funding_info = exchange_pb.PerpetualMarketFunding( + cumulative_funding="-107853477278881692857461", + cumulative_price="0", + last_timestamp=1708099200, + ) + perpetual_info = exchange_query_pb.PerpetualMarketState( + market_info=market_info, + funding_info=funding_info, + ) + mid_price_and_tob = exchange_pb.MidPriceAndTOB( + mid_price="2000000000000000000", + best_buy_price="1000000000000000000", + best_sell_price="3000000000000000000", + ) + full_market = exchange_query_pb.FullDerivativeMarket( + market=market, + perpetual_info=perpetual_info, + mark_price="33803835513327368963000000", + mid_price_and_tob=mid_price_and_tob, + ) + exchange_servicer.derivative_market_responses.append( + exchange_query_pb.QueryDerivativeMarketResponse( + market=full_market, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + status_string = exchange_pb.MarketStatus.Name(market.status) + market_response = await api.fetch_derivative_market( + market_id=market.market_id, + ) + expected_market = { + "market": { + "market": { + "ticker": market.ticker, + "oracleBase": market.oracle_base, + "oracleQuote": market.oracle_quote, + "oracleType": oracle_pb.OracleType.Name(market.oracle_type), + "oracleScaleFactor": market.oracle_scale_factor, + "quoteDenom": market.quote_denom, + "marketId": market.market_id, + "initialMarginRatio": market.initial_margin_ratio, + "maintenanceMarginRatio": market.maintenance_margin_ratio, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "isPerpetual": market.isPerpetual, + "status": status_string, + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + }, + "perpetualInfo": { + "marketInfo": { + "marketId": market_info.market_id, + "hourlyFundingRateCap": market_info.hourly_funding_rate_cap, + "hourlyInterestRate": market_info.hourly_interest_rate, + "nextFundingTimestamp": str(market_info.next_funding_timestamp), + "fundingInterval": str(market_info.funding_interval), + }, + "fundingInfo": { + "cumulativeFunding": funding_info.cumulative_funding, + "cumulativePrice": funding_info.cumulative_price, + "lastTimestamp": str(funding_info.last_timestamp), + }, + }, + "markPrice": full_market.mark_price, + "midPriceAndTob": { + "midPrice": mid_price_and_tob.mid_price, + "bestBuyPrice": mid_price_and_tob.best_buy_price, + "bestSellPrice": mid_price_and_tob.best_sell_price, + }, + } + } + + assert market_response == expected_market + + @pytest.mark.asyncio + async def test_fetch_derivative_market_address( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryDerivativeMarketAddressResponse( + address="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9", + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + ) + exchange_servicer.derivative_market_address_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + address = await api.fetch_derivative_market_address( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + expected_address = { + "address": response.address, + "subaccountId": response.subaccount_id, + } + + assert address == expected_address + + @pytest.mark.asyncio + async def test_fetch_subaccount_trade_nonce( + self, + exchange_servicer, + ): + response = exchange_query_pb.QuerySubaccountTradeNonceResponse(nonce=1234567879) + exchange_servicer.subaccount_trade_nonce_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + nonce = await api.fetch_subaccount_trade_nonce( + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + ) + expected_nonce = { + "nonce": response.nonce, + } + + assert nonce == expected_nonce + + @pytest.mark.asyncio + async def test_fetch_positions( + self, + exchange_servicer, + ): + position = exchange_pb.Position( + isLong=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + margin="2000000000000000000000000000000000", + cumulative_funding_entry="4000000", + ) + derivative_position = genesis_pb.DerivativePosition( + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + position=position, + ) + exchange_servicer.positions_responses.append( + exchange_query_pb.QueryPositionsResponse(state=[derivative_position]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + positions = await api.fetch_positions() + expected_positions = { + "state": [ + { + "subaccountId": derivative_position.subaccount_id, + "marketId": derivative_position.market_id, + "position": { + "isLong": position.isLong, + "quantity": position.quantity, + "entryPrice": position.entry_price, + "margin": position.margin, + "cumulativeFundingEntry": position.cumulative_funding_entry, + }, + }, + ], + } + + assert positions == expected_positions + + @pytest.mark.asyncio + async def test_fetch_subaccount_positions( + self, + exchange_servicer, + ): + position = exchange_pb.Position( + isLong=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + margin="2000000000000000000000000000000000", + cumulative_funding_entry="4000000", + ) + derivative_position = genesis_pb.DerivativePosition( + subaccount_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + position=position, + ) + exchange_servicer.subaccount_positions_responses.append( + exchange_query_pb.QuerySubaccountPositionsResponse(state=[derivative_position]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + positions = await api.fetch_subaccount_positions(subaccount_id=derivative_position.subaccount_id) + expected_positions = { + "state": [ + { + "subaccountId": derivative_position.subaccount_id, + "marketId": derivative_position.market_id, + "position": { + "isLong": position.isLong, + "quantity": position.quantity, + "entryPrice": position.entry_price, + "margin": position.margin, + "cumulativeFundingEntry": position.cumulative_funding_entry, + }, + }, + ], + } + + assert positions == expected_positions + + @pytest.mark.asyncio + async def test_fetch_subaccount_position_in_market( + self, + exchange_servicer, + ): + subaccount_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000" + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + position = exchange_pb.Position( + isLong=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + margin="2000000000000000000000000000000000", + cumulative_funding_entry="4000000", + ) + exchange_servicer.subaccount_position_in_market_responses.append( + exchange_query_pb.QuerySubaccountPositionInMarketResponse(state=position) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + position_response = await api.fetch_subaccount_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + expected_position = { + "state": { + "isLong": position.isLong, + "quantity": position.quantity, + "entryPrice": position.entry_price, + "margin": position.margin, + "cumulativeFundingEntry": position.cumulative_funding_entry, + }, + } + + assert position_response == expected_position + + @pytest.mark.asyncio + async def test_fetch_subaccount_effective_position_in_market( + self, + exchange_servicer, + ): + subaccount_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20000000000000000000000000" + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + + effective_position = exchange_query_pb.EffectivePosition( + is_long=True, + quantity="1000000000000000", + entry_price="2000000000000000000", + effective_margin="2000000000000000000000000000000000", + ) + exchange_servicer.subaccount_effective_position_in_market_responses.append( + exchange_query_pb.QuerySubaccountEffectivePositionInMarketResponse(state=effective_position) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + position_response = await api.fetch_subaccount_effective_position_in_market( + subaccount_id=subaccount_id, + market_id=market_id, + ) + expected_position = { + "state": { + "isLong": effective_position.is_long, + "quantity": effective_position.quantity, + "entryPrice": effective_position.entry_price, + "effectiveMargin": effective_position.effective_margin, + }, + } + + assert position_response == expected_position + + @pytest.mark.asyncio + async def test_fetch_perpetual_market_info( + self, + exchange_servicer, + ): + perpetual_market_info = exchange_pb.PerpetualMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + hourly_funding_rate_cap="625000000000000", + hourly_interest_rate="4166660000000", + next_funding_timestamp=1708099200, + funding_interval=3600, + ) + exchange_servicer.perpetual_market_info_responses.append( + exchange_query_pb.QueryPerpetualMarketInfoResponse(info=perpetual_market_info) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + market_info = await api.fetch_perpetual_market_info(market_id=perpetual_market_info.market_id) + expected_market_info = { + "info": { + "marketId": perpetual_market_info.market_id, + "hourlyFundingRateCap": perpetual_market_info.hourly_funding_rate_cap, + "hourlyInterestRate": perpetual_market_info.hourly_interest_rate, + "nextFundingTimestamp": str(perpetual_market_info.next_funding_timestamp), + "fundingInterval": str(perpetual_market_info.funding_interval), + } + } + + assert market_info == expected_market_info + + @pytest.mark.asyncio + async def test_fetch_expiry_futures_market_info( + self, + exchange_servicer, + ): + expiry_futures_market_info = exchange_pb.ExpiryFuturesMarketInfo( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + expiration_timestamp=1708099200, + twap_start_timestamp=1705566200, + expiration_twap_start_price_cumulative="1000000000000000000", + settlement_price="2000000000000000000", + ) + exchange_servicer.expiry_futures_market_info_responses.append( + exchange_query_pb.QueryExpiryFuturesMarketInfoResponse(info=expiry_futures_market_info) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + market_info = await api.fetch_expiry_futures_market_info(market_id=expiry_futures_market_info.market_id) + expected_market_info = { + "info": { + "marketId": expiry_futures_market_info.market_id, + "expirationTimestamp": str(expiry_futures_market_info.expiration_timestamp), + "twapStartTimestamp": str(expiry_futures_market_info.twap_start_timestamp), + "expirationTwapStartPriceCumulative": expiry_futures_market_info.expiration_twap_start_price_cumulative, + "settlementPrice": expiry_futures_market_info.settlement_price, + } + } + + assert market_info == expected_market_info + + @pytest.mark.asyncio + async def test_fetch_perpetual_market_funding( + self, + exchange_servicer, + ): + perpetual_market_funding = exchange_pb.PerpetualMarketFunding( + cumulative_funding="-107853477278881692857461", + cumulative_price="0", + last_timestamp=1708099200, + ) + exchange_servicer.perpetual_market_funding_responses.append( + exchange_query_pb.QueryPerpetualMarketFundingResponse(state=perpetual_market_funding) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + funding = await api.fetch_perpetual_market_funding( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + ) + expected_funding = { + "state": { + "cumulativeFunding": perpetual_market_funding.cumulative_funding, + "cumulativePrice": perpetual_market_funding.cumulative_price, + "lastTimestamp": str(perpetual_market_funding.last_timestamp), + } + } + + assert funding == expected_funding + + @pytest.mark.asyncio + async def test_fetch_subaccount_order_metadata( + self, + exchange_servicer, + ): + metadata = exchange_pb.SubaccountOrderbookMetadata( + vanilla_limit_order_count=1, + reduce_only_limit_order_count=2, + aggregate_reduce_only_quantity="1000000000000000", + aggregate_vanilla_quantity="2000000000000000", + vanilla_conditional_order_count=3, + reduce_only_conditional_order_count=4, + ) + subaccount_order_metadata = exchange_query_pb.SubaccountOrderbookMetadataWithMarket( + metadata=metadata, + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + isBuy=True, + ) + exchange_servicer.subaccount_order_metadata_responses.append( + exchange_query_pb.QuerySubaccountOrderMetadataResponse(metadata=[subaccount_order_metadata]) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + metadata_response = await api.fetch_subaccount_order_metadata( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001" + ) + expected_metadata = { + "metadata": [ + { + "metadata": { + "vanillaLimitOrderCount": metadata.vanilla_limit_order_count, + "reduceOnlyLimitOrderCount": metadata.reduce_only_limit_order_count, + "aggregateReduceOnlyQuantity": metadata.aggregate_reduce_only_quantity, + "aggregateVanillaQuantity": metadata.aggregate_vanilla_quantity, + "vanillaConditionalOrderCount": metadata.vanilla_conditional_order_count, + "reduceOnlyConditionalOrderCount": metadata.reduce_only_conditional_order_count, + }, + "marketId": subaccount_order_metadata.market_id, + "isBuy": subaccount_order_metadata.isBuy, + }, + ] + } + + assert metadata_response == expected_metadata + + @pytest.mark.asyncio + async def test_fetch_trade_reward_points( + self, + exchange_servicer, + ): + points = "40" + response = exchange_query_pb.QueryTradeRewardPointsResponse(account_trade_reward_points=[points]) + exchange_servicer.trade_reward_points_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + trade_reward_points = await api.fetch_trade_reward_points( + accounts=["inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"], + pending_pool_timestamp=1708099200, + ) + expected_trade_reward_points = {"accountTradeRewardPoints": [points]} + + assert trade_reward_points == expected_trade_reward_points + + @pytest.mark.asyncio + async def test_fetch_pending_trade_reward_points( + self, + exchange_servicer, + ): + points = "40" + response = exchange_query_pb.QueryTradeRewardPointsResponse(account_trade_reward_points=[points]) + exchange_servicer.pending_trade_reward_points_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + trade_reward_points = await api.fetch_pending_trade_reward_points( + accounts=["inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r"], + pending_pool_timestamp=1708099200, + ) + expected_trade_reward_points = {"accountTradeRewardPoints": [points]} + + assert trade_reward_points == expected_trade_reward_points + + @pytest.mark.asyncio + async def test_fetch_fee_discount_account_info( + self, + exchange_servicer, + ): + account_info = exchange_pb.FeeDiscountTierInfo( + maker_discount_rate="0.0001", + taker_discount_rate="0.0002", + staked_amount="1000000000", + volume="1000000000000000000", + ) + account_ttl = exchange_pb.FeeDiscountTierTTL( + tier=3, + ttl_timestamp=1708099200, + ) + response = exchange_query_pb.QueryFeeDiscountAccountInfoResponse( + tier_level=3, + account_info=account_info, + account_ttl=account_ttl, + ) + exchange_servicer.fee_discount_account_info_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + fee_discount = await api.fetch_fee_discount_account_info(account="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r") + expected_fee_discount = { + "tierLevel": str(response.tier_level), + "accountInfo": { + "makerDiscountRate": account_info.maker_discount_rate, + "takerDiscountRate": account_info.taker_discount_rate, + "stakedAmount": account_info.staked_amount, + "volume": account_info.volume, + }, + "accountTtl": { + "tier": str(account_ttl.tier), + "ttlTimestamp": str(account_ttl.ttl_timestamp), + }, + } + + assert fee_discount == expected_fee_discount + + @pytest.mark.asyncio + async def test_fetch_fee_discount_schedule( + self, + exchange_servicer, + ): + fee_discount_tier_info = exchange_pb.FeeDiscountTierInfo( + maker_discount_rate="0.0001", + taker_discount_rate="0.0002", + staked_amount="1000000000", + volume="1000000000000000000", + ) + fee_discount_schedule = exchange_pb.FeeDiscountSchedule( + bucket_count=3, + bucket_duration=3600, + quote_denoms=["peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"], + tier_infos=[fee_discount_tier_info], + disqualified_market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"], + ) + exchange_servicer.fee_discount_schedule_responses.append( + exchange_query_pb.QueryFeeDiscountScheduleResponse( + fee_discount_schedule=fee_discount_schedule, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + schedule = await api.fetch_fee_discount_schedule() + expected_schedule = { + "feeDiscountSchedule": { + "bucketCount": str(fee_discount_schedule.bucket_count), + "bucketDuration": str(fee_discount_schedule.bucket_duration), + "quoteDenoms": fee_discount_schedule.quote_denoms, + "tierInfos": [ + { + "makerDiscountRate": fee_discount_tier_info.maker_discount_rate, + "takerDiscountRate": fee_discount_tier_info.taker_discount_rate, + "stakedAmount": fee_discount_tier_info.staked_amount, + "volume": fee_discount_tier_info.volume, + } + ], + "disqualifiedMarketIds": fee_discount_schedule.disqualified_market_ids, + }, + } + + assert schedule == expected_schedule + + @pytest.mark.asyncio + async def test_fetch_balance_mismatches( + self, + exchange_servicer, + ): + balance_mismatch = exchange_query_pb.BalanceMismatch( + subaccountId="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + available="1000000000000000", + total="2000000000000000", + balance_hold="3000000000000000", + expected_total="4000000000000000", + difference="500000000000000", + ) + exchange_servicer.balance_mismatches_responses.append( + exchange_query_pb.QueryBalanceMismatchesResponse( + balance_mismatches=[balance_mismatch], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + mismatches = await api.fetch_balance_mismatches(dust_factor=20) + expected_mismatches = { + "balanceMismatches": [ + { + "subaccountId": balance_mismatch.subaccountId, + "denom": balance_mismatch.denom, + "available": balance_mismatch.available, + "total": balance_mismatch.total, + "balanceHold": balance_mismatch.balance_hold, + "expectedTotal": balance_mismatch.expected_total, + "difference": balance_mismatch.difference, + } + ], + } + + assert mismatches == expected_mismatches + + @pytest.mark.asyncio + async def test_fetch_balance_with_balance_holds( + self, + exchange_servicer, + ): + balance_with_balance_hold = exchange_query_pb.BalanceWithMarginHold( + subaccountId="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + available="1000000000000000", + total="2000000000000000", + balance_hold="3000000000000000", + ) + exchange_servicer.balance_with_balance_holds_responses.append( + exchange_query_pb.QueryBalanceWithBalanceHoldsResponse( + balance_with_balance_holds=[balance_with_balance_hold], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + balance = await api.fetch_balance_with_balance_holds() + expected_balance = { + "balanceWithBalanceHolds": [ + { + "subaccountId": balance_with_balance_hold.subaccountId, + "denom": balance_with_balance_hold.denom, + "available": balance_with_balance_hold.available, + "total": balance_with_balance_hold.total, + "balanceHold": balance_with_balance_hold.balance_hold, + } + ], + } + + assert balance == expected_balance + + @pytest.mark.asyncio + async def test_fetch_fee_discount_tier_statistics( + self, + exchange_servicer, + ): + tier_statistics = exchange_query_pb.TierStatistic( + tier=3, + count=30, + ) + exchange_servicer.fee_discount_tier_statistics_responses.append( + exchange_query_pb.QueryFeeDiscountTierStatisticsResponse( + statistics=[tier_statistics], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + statistics = await api.fetch_fee_discount_tier_statistics() + expected_statistics = { + "statistics": [ + { + "tier": str(tier_statistics.tier), + "count": str(tier_statistics.count), + } + ], + } + + assert statistics == expected_statistics + + @pytest.mark.asyncio + async def test_fetch_mito_vault_infos( + self, + exchange_servicer, + ): + master_address = "inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9" + derivative_address = "inj1zlh5" + spot_address = "inj1zlh6" + cw20_address = "inj1zlh7" + response = exchange_query_pb.MitoVaultInfosResponse( + master_addresses=[master_address], + derivative_addresses=[derivative_address], + spot_addresses=[spot_address], + cw20_addresses=[cw20_address], + ) + exchange_servicer.mito_vault_infos_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + mito_vaults = await api.fetch_mito_vault_infos() + expected_mito_vaults = { + "masterAddresses": [master_address], + "derivativeAddresses": [derivative_address], + "spotAddresses": [spot_address], + "cw20Addresses": [cw20_address], + } + + assert mito_vaults == expected_mito_vaults + + @pytest.mark.asyncio + async def test_fetch_market_id_from_vault( + self, + exchange_servicer, + ): + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + exchange_servicer.market_id_from_vault_responses.append( + exchange_query_pb.QueryMarketIDFromVaultResponse( + market_id=market_id, + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + market_id_response = await api.fetch_market_id_from_vault( + vault_address="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9" + ) + expected_market_id = { + "marketId": market_id, + } + + assert market_id_response == expected_market_id + + @pytest.mark.asyncio + async def test_fetch_historical_trade_records( + self, + exchange_servicer, + ): + latest_trade_record = exchange_pb.TradeRecord( + timestamp=1708099200, + price="2000000000000000000", + quantity="1000000000000000", + ) + trade_record = exchange_pb.TradeRecords( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + latest_trade_records=[latest_trade_record], + ) + exchange_servicer.historical_trade_records_responses.append( + exchange_query_pb.QueryHistoricalTradeRecordsResponse( + trade_records=[trade_record], + ) + ) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + records = await api.fetch_historical_trade_records(market_id=trade_record.market_id) + expected_records = { + "tradeRecords": [ + { + "marketId": trade_record.market_id, + "latestTradeRecords": [ + { + "timestamp": str(latest_trade_record.timestamp), + "price": latest_trade_record.price, + "quantity": latest_trade_record.quantity, + } + ], + }, + ], + } + + assert records == expected_records + + @pytest.mark.asyncio + async def test_fetch_is_opted_out_of_rewards( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryIsOptedOutOfRewardsResponse( + is_opted_out=False, + ) + exchange_servicer.is_opted_out_of_rewards_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + is_opted_out = await api.fetch_is_opted_out_of_rewards(account="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9") + expected_is_opted_out = { + "isOptedOut": response.is_opted_out, + } + + assert is_opted_out == expected_is_opted_out + + @pytest.mark.asyncio + async def test_fetch_opted_out_of_rewards_accounts( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryOptedOutOfRewardsAccountsResponse( + accounts=["inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9"], + ) + exchange_servicer.opted_out_of_rewards_accounts_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + opted_out = await api.fetch_opted_out_of_rewards_accounts() + expected_opted_out = { + "accounts": response.accounts, + } + + assert opted_out == expected_opted_out + + @pytest.mark.asyncio + async def test_fetch_market_volatility( + self, + exchange_servicer, + ): + history_metadata = oracle_pb.MetadataStatistics( + group_count=2, + records_sample_size=10, + mean="0.0001", + twap="0.0005", + first_timestamp=1702399200, + last_timestamp=1708099200, + min_price="1000000000000", + max_price="3000000000000", + median_price="2000000000000", + ) + trade_record = exchange_pb.TradeRecord( + timestamp=1708099200, + price="2000000000000000000", + quantity="1000000000000000", + ) + response = exchange_query_pb.QueryMarketVolatilityResponse( + volatility="0.0001", history_metadata=history_metadata, raw_history=[trade_record] + ) + exchange_servicer.market_volatility_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + volatility = await api.fetch_market_volatility( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + trade_grouping_sec=0, + max_age=28000000, + include_raw_history=True, + include_metadata=True, + ) + expected_volatility = { + "volatility": response.volatility, + "historyMetadata": { + "groupCount": history_metadata.group_count, + "recordsSampleSize": history_metadata.records_sample_size, + "mean": history_metadata.mean, + "twap": history_metadata.twap, + "firstTimestamp": str(history_metadata.first_timestamp), + "lastTimestamp": str(history_metadata.last_timestamp), + "minPrice": history_metadata.min_price, + "maxPrice": history_metadata.max_price, + "medianPrice": history_metadata.median_price, + }, + "rawHistory": [ + { + "timestamp": str(trade_record.timestamp), + "price": trade_record.price, + "quantity": trade_record.quantity, + } + ], + } + + assert volatility == expected_volatility + + @pytest.mark.asyncio + async def test_fetch_binary_options_markets( + self, + exchange_servicer, + ): + market = exchange_pb.BinaryOptionsMarket( + ticker="20250608/USDT", + oracle_symbol="0x2d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b3", + oracle_provider="Pyth", + oracle_type=9, + oracle_scale_factor=6, + expiration_timestamp=1708099200, + settlement_timestamp=1707099200, + admin="inj1zlh5sqevkfphtwnu9cul8p89vseme2eqt0snn9", + quote_denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + maker_fee_rate="-0.0001", + taker_fee_rate="0.001", + relayer_fee_share_rate="400000000000000000", + status=1, + min_price_tick_size="100000000000000000000", + min_quantity_tick_size="1000000000000000", + settlement_price="2000000000000000000", + ) + response = exchange_query_pb.QueryBinaryMarketsResponse( + markets=[market], + ) + exchange_servicer.binary_options_markets_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + markets = await api.fetch_binary_options_markets(status="Active") + expected_markets = { + "markets": [ + { + "ticker": market.ticker, + "oracleSymbol": market.oracle_symbol, + "oracleProvider": market.oracle_provider, + "oracleType": oracle_pb.OracleType.Name(market.oracle_type), + "oracleScaleFactor": market.oracle_scale_factor, + "expirationTimestamp": str(market.expiration_timestamp), + "settlementTimestamp": str(market.settlement_timestamp), + "admin": market.admin, + "quoteDenom": market.quote_denom, + "marketId": market.market_id, + "makerFeeRate": market.maker_fee_rate, + "takerFeeRate": market.taker_fee_rate, + "relayerFeeShareRate": market.relayer_fee_share_rate, + "status": exchange_pb.MarketStatus.Name(market.status), + "minPriceTickSize": market.min_price_tick_size, + "minQuantityTickSize": market.min_quantity_tick_size, + "settlementPrice": market.settlement_price, + }, + ] + } + + assert markets == expected_markets + + @pytest.mark.asyncio + async def test_fetch_trader_derivative_conditional_orders( + self, + exchange_servicer, + ): + order = exchange_query_pb.TrimmedDerivativeConditionalOrder( + price="2000000000000000000", + quantity="1000000000000000", + margin="2000000000000000000000000000000000", + triggerPrice="3000000000000000000", + isBuy=True, + isLimit=True, + order_hash="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + response = exchange_query_pb.QueryTraderDerivativeConditionalOrdersResponse(orders=[order]) + exchange_servicer.trader_derivative_conditional_orders_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + orders = await api.fetch_trader_derivative_conditional_orders( + subaccount_id="0x5303d92e49a619bb29de8fb6f59c0e7589213cc8000000000000000000000001", + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + expected_orders = { + "orders": [ + { + "price": order.price, + "quantity": order.quantity, + "margin": order.margin, + "triggerPrice": order.triggerPrice, + "isBuy": order.isBuy, + "isLimit": order.isLimit, + "orderHash": order.order_hash, + } + ] + } + + assert orders == expected_orders + + @pytest.mark.asyncio + async def test_fetch_market_atomic_execution_fee_multiplier( + self, + exchange_servicer, + ): + response = exchange_query_pb.QueryMarketAtomicExecutionFeeMultiplierResponse( + multiplier="100", + ) + exchange_servicer.market_atomic_execution_fee_multiplier_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + multiplier = await api.fetch_market_atomic_execution_fee_multiplier( + market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", + ) + expected_multiplier = { + "multiplier": response.multiplier, + } + + assert multiplier == expected_multiplier + + async def _dummy_metadata_provider(self): + return None From 17524aff42f95cd7f9b96294a683863e62722e41 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 27 Feb 2024 10:03:11 -0300 Subject: [PATCH 36/44] (feat) Added support for all chain exchange module messages in Composer. Added unit tests for new messages. Refactored example scripts to move them into separated subfolders for each module. --- ..._LocalOrderHash.py => 1_LocalOrderHash.py} | 101 +- ...OrderFail.py => 2_StreamEventOrderFail.py} | 0 .../35_MsgInstantBinaryOptionsMarketLaunch.py | 98 - ...Broadcaster.py => 3_MessageBroadcaster.py} | 21 +- ...4_MessageBroadcasterWithGranteeAccount.py} | 12 +- ... 5_MessageBroadcasterWithoutSimulation.py} | 19 +- ...terWithGranteeAccountWithoutSimulation.py} | 12 +- .../{49_ChainStream.py => 7_ChainStream.py} | 0 .../{18_MsgBid.py => auction/1_MsgBid.py} | 0 .../query/1_Account.py} | 0 .../{19_MsgGrant.py => authz/1_MsgGrant.py} | 0 .../{20_MsgExec.py => authz/2_MsgExec.py} | 10 +- .../{21_MsgRevoke.py => authz/3_MsgRevoke.py} | 0 .../4_MsgExecuteContractCompat.py} | 0 .../{27_Grants.py => authz/query/1_Grants.py} | 0 examples/chain_client/{ => bank}/1_MsgSend.py | 0 .../query/10_SendEnabled.py} | 0 .../query/1_BankBalance.py} | 0 .../query/2_BankBalances.py} | 0 .../query/3_SpendableBalances.py} | 0 .../query/4_SpendableBalancesByDenom.py} | 0 .../query/5_TotalSupply.py} | 0 .../query/6_SupplyOf.py} | 0 .../query/7_DenomMetadata.py} | 0 .../query/8_DenomsMetadata.py} | 0 .../query/9_DenomOwners.py} | 0 ...py => 10_MsgCreateDerivativeLimitOrder.py} | 14 +- ...y => 11_MsgCreateDerivativeMarketOrder.py} | 12 +- ...rder.py => 12_MsgCancelDerivativeOrder.py} | 2 +- .../13_MsgInstantBinaryOptionsMarketLaunch.py | 61 + ...=> 14_MsgCreateBinaryOptionsLimitOrder.py} | 13 +- ...> 15_MsgCreateBinaryOptionsMarketOrder.py} | 12 +- ...r.py => 16_MsgCancelBinaryOptionsOrder.py} | 2 +- ...ransfer.py => 17_MsgSubaccountTransfer.py} | 5 +- ...lTransfer.py => 18_MsgExternalTransfer.py} | 5 +- .../exchange/19_MsgLiquidatePosition.py | 15 +- .../chain_client/exchange/1_MsgDeposit.py | 4 +- .../20_MsgIncreasePositionMargin.py} | 5 +- ...ewardsOptOut.py => 21_MsgRewardsOptOut.py} | 2 +- .../22_MsgAdminUpdateBinaryOptionsMarket.py} | 5 +- .../{9_MsgWithdraw.py => 2_MsgWithdraw.py} | 2 +- .../exchange/3_MsgInstantSpotMarketLaunch.py | 54 + .../4_MsgInstantPerpetualMarketLaunch.py | 61 + .../5_MsgInstantExpiryFuturesMarketLaunch.py | 62 + ...tOrder.py => 6_MsgCreateSpotLimitOrder.py} | 10 +- ...Order.py => 7_MsgCreateSpotMarketOrder.py} | 11 +- ...elSpotOrder.py => 8_MsgCancelSpotOrder.py} | 0 ...ateOrders.py => 9_MsgBatchUpdateOrders.py} | 53 +- .../1_MsgCreateInsuranceFund.py} | 0 .../2_MsgUnderwrite.py} | 0 .../3_MsgRequestRedemption.py} | 0 .../1_MsgRelayPriceFeedPrice.py} | 0 .../2_MsgRelayProviderPrices.py} | 0 .../1_MsgSendToEth.py} | 0 .../1_MsgDelegate.py} | 0 .../1_CreateDenom.py} | 0 .../2_MsgMint.py} | 0 .../3_MsgBurn.py} | 0 .../4_MsgChangeAdmin.py} | 0 .../5_MsgSetDenomMetadata.py} | 0 .../query/1_DenomAuthorityMetadata.py} | 0 .../query/2_DenomsFromCreator.py} | 0 .../query/3_TokenfactoryModuleState.py} | 0 .../{37_GetTx.py => tx/query/1_GetTx.py} | 0 .../1_MsgExecuteContract.py} | 0 .../query/10_ContractsByCreator.py} | 0 .../query/1_ContractInfo.py} | 0 .../query/2_ContractHistory.py} | 0 .../query/3_ContractsByCode.py} | 0 .../query/4_AllContractsState.py} | 0 .../query/5_RawContractState.py} | 0 .../query/6_SmartContractState.py} | 0 .../query/7_SmartContractCode.py} | 0 .../query/8_SmartContractCodes.py} | 0 .../query/9_SmartContractPinnedCodes.py} | 0 pyinjective/composer.py | 1751 +++++++++++++---- pyinjective/core/market.py | 11 + tests/core/test_gas_limit_estimator.py | 158 +- tests/core/test_market.py | 36 + ...essage_based_transaction_fee_calculator.py | 27 +- tests/test_composer.py | 1466 ++++++++++++-- tests/test_composer_deprecation_warnings.py | 522 +++++ tests/test_orderhash.py | 20 +- 83 files changed, 3740 insertions(+), 934 deletions(-) rename examples/chain_client/{0_LocalOrderHash.py => 1_LocalOrderHash.py} (75%) rename examples/chain_client/{38_StreamEventOrderFail.py => 2_StreamEventOrderFail.py} (100%) delete mode 100644 examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py rename examples/chain_client/{44_MessageBroadcaster.py => 3_MessageBroadcaster.py} (84%) rename examples/chain_client/{45_MessageBroadcasterWithGranteeAccount.py => 4_MessageBroadcasterWithGranteeAccount.py} (91%) rename examples/chain_client/{46_MessageBroadcasterWithoutSimulation.py => 5_MessageBroadcasterWithoutSimulation.py} (86%) rename examples/chain_client/{47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py => 6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py} (91%) rename examples/chain_client/{49_ChainStream.py => 7_ChainStream.py} (100%) rename examples/chain_client/{18_MsgBid.py => auction/1_MsgBid.py} (100%) rename examples/chain_client/{39_Account.py => auth/query/1_Account.py} (100%) rename examples/chain_client/{19_MsgGrant.py => authz/1_MsgGrant.py} (100%) rename examples/chain_client/{20_MsgExec.py => authz/2_MsgExec.py} (95%) rename examples/chain_client/{21_MsgRevoke.py => authz/3_MsgRevoke.py} (100%) rename examples/chain_client/{76_MsgExecuteContractCompat.py => authz/4_MsgExecuteContractCompat.py} (100%) rename examples/chain_client/{27_Grants.py => authz/query/1_Grants.py} (100%) rename examples/chain_client/{ => bank}/1_MsgSend.py (100%) rename examples/chain_client/{57_SendEnabled.py => bank/query/10_SendEnabled.py} (100%) rename examples/chain_client/{29_BankBalance.py => bank/query/1_BankBalance.py} (100%) rename examples/chain_client/{28_BankBalances.py => bank/query/2_BankBalances.py} (100%) rename examples/chain_client/{50_SpendableBalances.py => bank/query/3_SpendableBalances.py} (100%) rename examples/chain_client/{51_SpendableBalancesByDenom.py => bank/query/4_SpendableBalancesByDenom.py} (100%) rename examples/chain_client/{52_TotalSupply.py => bank/query/5_TotalSupply.py} (100%) rename examples/chain_client/{53_SupplyOf.py => bank/query/6_SupplyOf.py} (100%) rename examples/chain_client/{54_DenomMetadata.py => bank/query/7_DenomMetadata.py} (100%) rename examples/chain_client/{55_DenomsMetadata.py => bank/query/8_DenomsMetadata.py} (100%) rename examples/chain_client/{56_DenomOwners.py => bank/query/9_DenomOwners.py} (100%) rename examples/chain_client/exchange/{6_MsgCreateDerivativeLimitOrder.py => 10_MsgCreateDerivativeLimitOrder.py} (90%) rename examples/chain_client/exchange/{7_MsgCreateDerivativeMarketOrder.py => 11_MsgCreateDerivativeMarketOrder.py} (90%) rename examples/chain_client/exchange/{8_MsgCancelDerivativeOrder.py => 12_MsgCancelDerivativeOrder.py} (98%) create mode 100644 examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py rename examples/chain_client/exchange/{16_MsgCreateBinaryOptionsLimitOrder.py => 14_MsgCreateBinaryOptionsLimitOrder.py} (93%) rename examples/chain_client/exchange/{17_MsgCreateBinaryOptionsMarketOrder.py => 15_MsgCreateBinaryOptionsMarketOrder.py} (90%) rename examples/chain_client/exchange/{18_MsgCancelBinaryOptionsOrder.py => 16_MsgCancelBinaryOptionsOrder.py} (98%) rename examples/chain_client/exchange/{10_MsgSubaccountTransfer.py => 17_MsgSubaccountTransfer.py} (96%) rename examples/chain_client/exchange/{15_ExternalTransfer.py => 18_MsgExternalTransfer.py} (96%) rename examples/chain_client/{13_MsgIncreasePositionMargin.py => exchange/20_MsgIncreasePositionMargin.py} (96%) rename examples/chain_client/exchange/{12_MsgRewardsOptOut.py => 21_MsgRewardsOptOut.py} (97%) rename examples/chain_client/{34_MsgAdminUpdateBinaryOptionsMarket.py => exchange/22_MsgAdminUpdateBinaryOptionsMarket.py} (96%) rename examples/chain_client/exchange/{9_MsgWithdraw.py => 2_MsgWithdraw.py} (95%) create mode 100644 examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py create mode 100644 examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py create mode 100644 examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py rename examples/chain_client/exchange/{3_MsgCreateSpotLimitOrder.py => 6_MsgCreateSpotLimitOrder.py} (94%) rename examples/chain_client/exchange/{4_MsgCreateSpotMarketOrder.py => 7_MsgCreateSpotMarketOrder.py} (94%) rename examples/chain_client/exchange/{5_MsgCancelSpotOrder.py => 8_MsgCancelSpotOrder.py} (100%) rename examples/chain_client/exchange/{11_MsgBatchUpdateOrders.py => 9_MsgBatchUpdateOrders.py} (83%) rename examples/chain_client/{41_MsgCreateInsuranceFund.py => insurance/1_MsgCreateInsuranceFund.py} (100%) rename examples/chain_client/{42_MsgUnderwrite.py => insurance/2_MsgUnderwrite.py} (100%) rename examples/chain_client/{43_MsgRequestRedemption.py => insurance/3_MsgRequestRedemption.py} (100%) rename examples/chain_client/{23_MsgRelayPriceFeedPrice.py => oracle/1_MsgRelayPriceFeedPrice.py} (100%) rename examples/chain_client/{36_MsgRelayProviderPrices.py => oracle/2_MsgRelayProviderPrices.py} (100%) rename examples/chain_client/{22_MsgSendToEth.py => peggy/1_MsgSendToEth.py} (100%) rename examples/chain_client/{25_MsgDelegate.py => staking/1_MsgDelegate.py} (100%) rename examples/chain_client/{71_CreateDenom.py => tokenfactory/1_CreateDenom.py} (100%) rename examples/chain_client/{72_MsgMint.py => tokenfactory/2_MsgMint.py} (100%) rename examples/chain_client/{73_MsgBurn.py => tokenfactory/3_MsgBurn.py} (100%) rename examples/chain_client/{75_MsgChangeAdmin.py => tokenfactory/4_MsgChangeAdmin.py} (100%) rename examples/chain_client/{74_MsgSetDenomMetadata.py => tokenfactory/5_MsgSetDenomMetadata.py} (100%) rename examples/chain_client/{68_DenomAuthorityMetadata.py => tokenfactory/query/1_DenomAuthorityMetadata.py} (100%) rename examples/chain_client/{69_DenomsFromCreator.py => tokenfactory/query/2_DenomsFromCreator.py} (100%) rename examples/chain_client/{70_TokenfactoryModuleState.py => tokenfactory/query/3_TokenfactoryModuleState.py} (100%) rename examples/chain_client/{37_GetTx.py => tx/query/1_GetTx.py} (100%) rename examples/chain_client/{40_MsgExecuteContract.py => wasm/1_MsgExecuteContract.py} (100%) rename examples/chain_client/{67_ContractsByCreator.py => wasm/query/10_ContractsByCreator.py} (100%) rename examples/chain_client/{58_ContractInfo.py => wasm/query/1_ContractInfo.py} (100%) rename examples/chain_client/{59_ContractHistory.py => wasm/query/2_ContractHistory.py} (100%) rename examples/chain_client/{60_ContractsByCode.py => wasm/query/3_ContractsByCode.py} (100%) rename examples/chain_client/{61_AllContractsState.py => wasm/query/4_AllContractsState.py} (100%) rename examples/chain_client/{62_RawContractState.py => wasm/query/5_RawContractState.py} (100%) rename examples/chain_client/{63_SmartContractState.py => wasm/query/6_SmartContractState.py} (100%) rename examples/chain_client/{64_SmartContractCode.py => wasm/query/7_SmartContractCode.py} (100%) rename examples/chain_client/{65_SmartContractCodes.py => wasm/query/8_SmartContractCodes.py} (100%) rename examples/chain_client/{66_SmartContractPinnedCodes.py => wasm/query/9_SmartContractPinnedCodes.py} (100%) create mode 100644 tests/test_composer_deprecation_warnings.py diff --git a/examples/chain_client/0_LocalOrderHash.py b/examples/chain_client/1_LocalOrderHash.py similarity index 75% rename from examples/chain_client/0_LocalOrderHash.py rename to examples/chain_client/1_LocalOrderHash.py index 770ad5bf..fbec8988 100644 --- a/examples/chain_client/0_LocalOrderHash.py +++ b/examples/chain_client/1_LocalOrderHash.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -40,57 +41,59 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" spot_orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.524, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("0.524"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=27.92, - quantity=0.01, - is_buy=False, - is_po=False, + price=Decimal("27.92"), + quantity=Decimal("0.01"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] derivative_orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=10500, - quantity=0.01, - leverage=1.5, - is_buy=True, - is_po=False, + price=Decimal(10500), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(10500), leverage=Decimal(2), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=65111, - quantity=0.01, - leverage=2, - is_buy=False, - is_reduce_only=False, + price=Decimal(65111), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(65111), leverage=Decimal(2), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ), ] # prepare tx msg - spot_msg = composer.MsgBatchCreateSpotLimitOrders(sender=address.to_acc_bech32(), orders=spot_orders) + spot_msg = composer.msg_batch_create_spot_limit_orders(sender=address.to_acc_bech32(), orders=spot_orders) - deriv_msg = composer.MsgBatchCreateDerivativeLimitOrders(sender=address.to_acc_bech32(), orders=derivative_orders) + deriv_msg = composer.msg_batch_create_derivative_limit_orders( + sender=address.to_acc_bech32(), orders=derivative_orders + ) # compute order hashes order_hashes = order_hash_manager.compute_order_hashes( @@ -167,57 +170,59 @@ async def main() -> None: print("gas fee: {} INJ".format(gas_fee)) spot_orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=1.524, - quantity=0.01, - is_buy=True, - is_po=True, + price=Decimal("1.524"), + quantity=Decimal("0.01"), + order_type="BUY_PO", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=27.92, - quantity=0.01, - is_buy=False, - is_po=False, + price=Decimal("27.92"), + quantity=Decimal("0.01"), + order_type="SELL_PO", cid=str(uuid.uuid4()), ), ] derivative_orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=25111, - quantity=0.01, - leverage=1.5, - is_buy=True, - is_po=False, + price=Decimal(25111), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(25111), leverage=Decimal("1.5"), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.DerivativeOrder( + composer.derivative_order( market_id=deriv_market_id, subaccount_id=subaccount_id_2, fee_recipient=fee_recipient, - price=65111, - quantity=0.01, - leverage=2, - is_buy=False, - is_reduce_only=False, + price=Decimal(65111), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(25111), leverage=Decimal(2), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ), ] # prepare tx msg - spot_msg = composer.MsgBatchCreateSpotLimitOrders(sender=address.to_acc_bech32(), orders=spot_orders) + spot_msg = composer.msg_batch_create_spot_limit_orders(sender=address.to_acc_bech32(), orders=spot_orders) - deriv_msg = composer.MsgBatchCreateDerivativeLimitOrders(sender=address.to_acc_bech32(), orders=derivative_orders) + deriv_msg = composer.msg_batch_create_derivative_limit_orders( + sender=address.to_acc_bech32(), orders=derivative_orders + ) # compute order hashes order_hashes = order_hash_manager.compute_order_hashes( diff --git a/examples/chain_client/38_StreamEventOrderFail.py b/examples/chain_client/2_StreamEventOrderFail.py similarity index 100% rename from examples/chain_client/38_StreamEventOrderFail.py rename to examples/chain_client/2_StreamEventOrderFail.py diff --git a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py deleted file mode 100644 index 7b8a6567..00000000 --- a/examples/chain_client/35_MsgInstantBinaryOptionsMarketLaunch.py +++ /dev/null @@ -1,98 +0,0 @@ -import asyncio -import os - -import dotenv -from grpc import RpcError - -from pyinjective.async_client import AsyncClient -from pyinjective.constant import GAS_FEE_BUFFER_AMOUNT, GAS_PRICE -from pyinjective.core.network import Network -from pyinjective.transaction import Transaction -from pyinjective.wallet import PrivateKey - - -async def main() -> None: - dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") - - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - composer = await client.composer() - await client.sync_timeout_height() - - # load account - priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - # prepare tx msg - msg = composer.MsgInstantBinaryOptionsMarketLaunch( - sender=address.to_acc_bech32(), - admin=address.to_acc_bech32(), - ticker="UFC-KHABIB-TKO-05/30/2023", - oracle_symbol="UFC-KHABIB-TKO-05/30/2023", - oracle_provider="UFC", - oracle_type="Provider", - quote_denom="peggy0xdAC17F958D2ee523a2206206994597C13D831ec7", - quote_decimals=6, - oracle_scale_factor=6, - maker_fee_rate=0.0005, # 0.05% - taker_fee_rate=0.0010, # 0.10% - expiration_timestamp=1680730982, - settlement_timestamp=1690730982, - min_price_tick_size=0.01, - min_quantity_tick_size=0.01, - ) - - # build sim tx - tx = ( - Transaction() - .with_messages(msg) - .with_sequence(client.get_sequence()) - .with_account_num(client.get_number()) - .with_chain_id(network.chain_id) - ) - sim_sign_doc = tx.get_sign_doc(pub_key) - sim_sig = priv_key.sign(sim_sign_doc.SerializeToString()) - sim_tx_raw_bytes = tx.get_tx_data(sim_sig, pub_key) - - # simulate tx - try: - sim_res = await client.simulate(sim_tx_raw_bytes) - except RpcError as ex: - print(ex) - return - - sim_res_msg = sim_res["result"]["msgResponses"] - print("---Simulation Response---") - print(sim_res_msg) - - # build tx - gas_price = GAS_PRICE - gas_limit = int(sim_res["gasInfo"]["gasUsed"]) + GAS_FEE_BUFFER_AMOUNT # add buffer for gas fee computation - gas_fee = "{:.18f}".format((gas_price * gas_limit) / pow(10, 18)).rstrip("0") - fee = [ - composer.coin( - amount=gas_price * gas_limit, - denom=network.fee_denom, - ) - ] - tx = tx.with_gas(gas_limit).with_fee(fee).with_memo("").with_timeout_height(client.timeout_height) - sign_doc = tx.get_sign_doc(pub_key) - sig = priv_key.sign(sign_doc.SerializeToString()) - tx_raw_bytes = tx.get_tx_data(sig, pub_key) - - # broadcast tx: send_tx_async_mode, send_tx_sync_mode, send_tx_block_mode - res = await client.broadcast_tx_sync_mode(tx_raw_bytes) - print("---Transaction Response---") - print(res) - print("gas wanted: {}".format(gas_limit)) - print("gas fee: {} INJ".format(gas_fee)) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/44_MessageBroadcaster.py b/examples/chain_client/3_MessageBroadcaster.py similarity index 84% rename from examples/chain_client/44_MessageBroadcaster.py rename to examples/chain_client/3_MessageBroadcaster.py index 114a8700..6bd67033 100644 --- a/examples/chain_client/44_MessageBroadcaster.py +++ b/examples/chain_client/3_MessageBroadcaster.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -34,24 +35,22 @@ async def main() -> None: spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" spot_orders_to_create = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=3, - quantity=55, - is_buy=True, - is_po=False, - cid=str(uuid.uuid4()), + price=Decimal("3"), + quantity=Decimal("55"), + order_type="BUY", + cid=(str(uuid.uuid4())), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=300, - quantity=55, - is_buy=False, - is_po=False, + price=Decimal("300"), + quantity=Decimal("55"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] diff --git a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py b/examples/chain_client/4_MessageBroadcasterWithGranteeAccount.py similarity index 91% rename from examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py rename to examples/chain_client/4_MessageBroadcasterWithGranteeAccount.py index 8c0166e2..4e08397b 100644 --- a/examples/chain_client/45_MessageBroadcasterWithGranteeAccount.py +++ b/examples/chain_client/4_MessageBroadcasterWithGranteeAccount.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -40,15 +41,14 @@ async def main() -> None: granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) - msg = composer.MsgCreateSpotLimitOrder( - sender=granter_inj_address, + msg = composer.msg_create_spot_limit_order( market_id=market_id, + sender=granter_inj_address, subaccount_id=granter_subaccount_id, fee_recipient=address.to_acc_bech32(), - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py b/examples/chain_client/5_MessageBroadcasterWithoutSimulation.py similarity index 86% rename from examples/chain_client/46_MessageBroadcasterWithoutSimulation.py rename to examples/chain_client/5_MessageBroadcasterWithoutSimulation.py index e6e87c5a..54a79bf8 100644 --- a/examples/chain_client/46_MessageBroadcasterWithoutSimulation.py +++ b/examples/chain_client/5_MessageBroadcasterWithoutSimulation.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -34,24 +35,22 @@ async def main() -> None: spot_market_id_create = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" spot_orders_to_create = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=3, - quantity=55, - is_buy=True, - is_po=False, + price=Decimal("3"), + quantity=Decimal("55"), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=300, - quantity=55, - is_buy=False, - is_po=False, + price=Decimal("300"), + quantity=Decimal("55"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] diff --git a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py b/examples/chain_client/6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py similarity index 91% rename from examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py rename to examples/chain_client/6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py index b95114b7..4b7fbd2e 100644 --- a/examples/chain_client/47_MessageBroadcasterWithGranteeAccountWithoutSimulation.py +++ b/examples/chain_client/6_MessageBroadcasterWithGranteeAccountWithoutSimulation.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv @@ -39,15 +40,14 @@ async def main() -> None: granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) - msg = composer.MsgCreateSpotLimitOrder( - sender=granter_inj_address, + msg = composer.msg_create_spot_limit_order( market_id=market_id, + sender=granter_inj_address, subaccount_id=granter_subaccount_id, fee_recipient=address.to_acc_bech32(), - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/49_ChainStream.py b/examples/chain_client/7_ChainStream.py similarity index 100% rename from examples/chain_client/49_ChainStream.py rename to examples/chain_client/7_ChainStream.py diff --git a/examples/chain_client/18_MsgBid.py b/examples/chain_client/auction/1_MsgBid.py similarity index 100% rename from examples/chain_client/18_MsgBid.py rename to examples/chain_client/auction/1_MsgBid.py diff --git a/examples/chain_client/39_Account.py b/examples/chain_client/auth/query/1_Account.py similarity index 100% rename from examples/chain_client/39_Account.py rename to examples/chain_client/auth/query/1_Account.py diff --git a/examples/chain_client/19_MsgGrant.py b/examples/chain_client/authz/1_MsgGrant.py similarity index 100% rename from examples/chain_client/19_MsgGrant.py rename to examples/chain_client/authz/1_MsgGrant.py diff --git a/examples/chain_client/20_MsgExec.py b/examples/chain_client/authz/2_MsgExec.py similarity index 95% rename from examples/chain_client/20_MsgExec.py rename to examples/chain_client/authz/2_MsgExec.py index 1203ff90..8d9891a5 100644 --- a/examples/chain_client/20_MsgExec.py +++ b/examples/chain_client/authz/2_MsgExec.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -37,15 +38,14 @@ async def main() -> None: granter_address = Address.from_acc_bech32(granter_inj_address) granter_subaccount_id = granter_address.get_subaccount_id(index=0) - msg0 = composer.MsgCreateSpotLimitOrder( + msg0 = composer.msg_create_spot_limit_order( sender=granter_inj_address, market_id=market_id, subaccount_id=granter_subaccount_id, fee_recipient=grantee, - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/21_MsgRevoke.py b/examples/chain_client/authz/3_MsgRevoke.py similarity index 100% rename from examples/chain_client/21_MsgRevoke.py rename to examples/chain_client/authz/3_MsgRevoke.py diff --git a/examples/chain_client/76_MsgExecuteContractCompat.py b/examples/chain_client/authz/4_MsgExecuteContractCompat.py similarity index 100% rename from examples/chain_client/76_MsgExecuteContractCompat.py rename to examples/chain_client/authz/4_MsgExecuteContractCompat.py diff --git a/examples/chain_client/27_Grants.py b/examples/chain_client/authz/query/1_Grants.py similarity index 100% rename from examples/chain_client/27_Grants.py rename to examples/chain_client/authz/query/1_Grants.py diff --git a/examples/chain_client/1_MsgSend.py b/examples/chain_client/bank/1_MsgSend.py similarity index 100% rename from examples/chain_client/1_MsgSend.py rename to examples/chain_client/bank/1_MsgSend.py diff --git a/examples/chain_client/57_SendEnabled.py b/examples/chain_client/bank/query/10_SendEnabled.py similarity index 100% rename from examples/chain_client/57_SendEnabled.py rename to examples/chain_client/bank/query/10_SendEnabled.py diff --git a/examples/chain_client/29_BankBalance.py b/examples/chain_client/bank/query/1_BankBalance.py similarity index 100% rename from examples/chain_client/29_BankBalance.py rename to examples/chain_client/bank/query/1_BankBalance.py diff --git a/examples/chain_client/28_BankBalances.py b/examples/chain_client/bank/query/2_BankBalances.py similarity index 100% rename from examples/chain_client/28_BankBalances.py rename to examples/chain_client/bank/query/2_BankBalances.py diff --git a/examples/chain_client/50_SpendableBalances.py b/examples/chain_client/bank/query/3_SpendableBalances.py similarity index 100% rename from examples/chain_client/50_SpendableBalances.py rename to examples/chain_client/bank/query/3_SpendableBalances.py diff --git a/examples/chain_client/51_SpendableBalancesByDenom.py b/examples/chain_client/bank/query/4_SpendableBalancesByDenom.py similarity index 100% rename from examples/chain_client/51_SpendableBalancesByDenom.py rename to examples/chain_client/bank/query/4_SpendableBalancesByDenom.py diff --git a/examples/chain_client/52_TotalSupply.py b/examples/chain_client/bank/query/5_TotalSupply.py similarity index 100% rename from examples/chain_client/52_TotalSupply.py rename to examples/chain_client/bank/query/5_TotalSupply.py diff --git a/examples/chain_client/53_SupplyOf.py b/examples/chain_client/bank/query/6_SupplyOf.py similarity index 100% rename from examples/chain_client/53_SupplyOf.py rename to examples/chain_client/bank/query/6_SupplyOf.py diff --git a/examples/chain_client/54_DenomMetadata.py b/examples/chain_client/bank/query/7_DenomMetadata.py similarity index 100% rename from examples/chain_client/54_DenomMetadata.py rename to examples/chain_client/bank/query/7_DenomMetadata.py diff --git a/examples/chain_client/55_DenomsMetadata.py b/examples/chain_client/bank/query/8_DenomsMetadata.py similarity index 100% rename from examples/chain_client/55_DenomsMetadata.py rename to examples/chain_client/bank/query/8_DenomsMetadata.py diff --git a/examples/chain_client/56_DenomOwners.py b/examples/chain_client/bank/query/9_DenomOwners.py similarity index 100% rename from examples/chain_client/56_DenomOwners.py rename to examples/chain_client/bank/query/9_DenomOwners.py diff --git a/examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py similarity index 90% rename from examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py rename to examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py index 41a19307..4e0ff327 100644 --- a/examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,16 +37,17 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateDerivativeLimitOrder( + msg = composer.msg_create_derivative_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=50000, - quantity=0.1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(50000), + quantity=Decimal(0.1), + margin=composer.calculate_margin( + quantity=Decimal(0.1), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py similarity index 90% rename from examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py rename to examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py index 37b305ed..dfedf6d6 100644 --- a/examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py +++ b/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,15 +37,16 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateDerivativeMarketOrder( + msg = composer.msg_create_derivative_market_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=50000, - quantity=0.01, - leverage=3, - is_buy=True, + price=Decimal(50000), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(50000), leverage=Decimal(3), is_reduce_only=False + ), cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py b/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py similarity index 98% rename from examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py rename to examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py index 43180b1f..20be2bd0 100644 --- a/examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py +++ b/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py @@ -35,7 +35,7 @@ async def main() -> None: order_hash = "0x667ee6f37f6d06bf473f4e1434e92ac98ff43c785405e2a511a0843daeca2de9" # prepare tx msg - msg = composer.MsgCancelDerivativeOrder( + msg = composer.msg_cancel_derivative_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash ) diff --git a/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py new file mode 100644 index 00000000..a1ebde82 --- /dev/null +++ b/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py @@ -0,0 +1,61 @@ +import asyncio +import os + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + composer = await client.composer() + await client.sync_timeout_height() + + message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( + network=network, + private_key=configured_private_key, + ) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + message = composer.msg_instant_binary_options_market_launch( + sender=address.to_acc_bech32(), + ticker="UFC-KHABIB-TKO-05/30/2023", + oracle_symbol="UFC-KHABIB-TKO-05/30/2023", + oracle_provider="UFC", + oracle_type="Provider", + quote_decimals=6, + oracle_scale_factor=6, + maker_fee_rate=0.0005, # 0.05% + taker_fee_rate=0.0010, # 0.10% + expiration_timestamp=1680730982, + settlement_timestamp=1690730982, + admin=address.to_acc_bech32(), + quote_denom="peggy0xdAC17F958D2ee523a2206206994597C13D831ec7", + min_price_tick_size=0.01, + min_quantity_tick_size=0.01, + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py similarity index 93% rename from examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py rename to examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py index 2a58e173..5ad8c59e 100644 --- a/examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py +++ b/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -40,17 +41,17 @@ async def main() -> None: denom = Denom(description="desc", base=0, quote=6, min_price_tick_size=1000, min_quantity_tick_size=0.0001) # prepare tx msg - msg = composer.MsgCreateBinaryOptionsLimitOrder( + msg = composer.msg_create_binary_options_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.5, - quantity=1, - is_buy=False, - is_reduce_only=False, - denom=denom, + price=Decimal("0.5"), + quantity=Decimal("1"), + margin=Decimal("0.5"), + order_type="BUY", cid=str(uuid.uuid4()), + denom=denom, ) # build sim tx diff --git a/examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py similarity index 90% rename from examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py rename to examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py index 2d07658f..9b68bc85 100644 --- a/examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py +++ b/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,15 +37,16 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateBinaryOptionsMarketOrder( + msg = composer.msg_create_binary_options_market_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.5, - quantity=1, - is_buy=True, - is_reduce_only=False, + price=Decimal("0.5"), + quantity=Decimal(1), + margin=composer.calculate_margin( + quantity=Decimal(1), price=Decimal("0.5"), leverage=Decimal(1), is_reduce_only=False + ), cid=str(uuid.uuid4()), ) # build sim tx diff --git a/examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py similarity index 98% rename from examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py rename to examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py index 82107f3c..582c6dc6 100644 --- a/examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py +++ b/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py @@ -35,7 +35,7 @@ async def main() -> None: order_hash = "a975fbd72b874bdbf5caf5e1e8e2653937f33ce6dd14d241c06c8b1f7b56be46" # prepare tx msg - msg = composer.MsgCancelBinaryOptionsOrder( + msg = composer.msg_cancel_binary_options_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash ) # build sim tx diff --git a/examples/chain_client/exchange/10_MsgSubaccountTransfer.py b/examples/chain_client/exchange/17_MsgSubaccountTransfer.py similarity index 96% rename from examples/chain_client/exchange/10_MsgSubaccountTransfer.py rename to examples/chain_client/exchange/17_MsgSubaccountTransfer.py index b68717b2..a50fc0cf 100644 --- a/examples/chain_client/exchange/10_MsgSubaccountTransfer.py +++ b/examples/chain_client/exchange/17_MsgSubaccountTransfer.py @@ -1,5 +1,6 @@ import asyncio import os +from decimal import Decimal import dotenv from grpc import RpcError @@ -32,11 +33,11 @@ async def main() -> None: dest_subaccount_id = address.get_subaccount_id(index=1) # prepare tx msg - msg = composer.MsgSubaccountTransfer( + msg = composer.msg_subaccount_transfer( sender=address.to_acc_bech32(), source_subaccount_id=subaccount_id, destination_subaccount_id=dest_subaccount_id, - amount=100, + amount=Decimal(100), denom="INJ", ) diff --git a/examples/chain_client/exchange/15_ExternalTransfer.py b/examples/chain_client/exchange/18_MsgExternalTransfer.py similarity index 96% rename from examples/chain_client/exchange/15_ExternalTransfer.py rename to examples/chain_client/exchange/18_MsgExternalTransfer.py index 3200be34..2bcc86a1 100644 --- a/examples/chain_client/exchange/15_ExternalTransfer.py +++ b/examples/chain_client/exchange/18_MsgExternalTransfer.py @@ -1,5 +1,6 @@ import asyncio import os +from decimal import Decimal import dotenv from grpc import RpcError @@ -32,11 +33,11 @@ async def main() -> None: dest_subaccount_id = "0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000" # prepare tx msg - msg = composer.MsgExternalTransfer( + msg = composer.msg_external_transfer( sender=address.to_acc_bech32(), source_subaccount_id=subaccount_id, destination_subaccount_id=dest_subaccount_id, - amount=100, + amount=Decimal(100), denom="INJ", ) diff --git a/examples/chain_client/exchange/19_MsgLiquidatePosition.py b/examples/chain_client/exchange/19_MsgLiquidatePosition.py index d80ba385..9788b865 100644 --- a/examples/chain_client/exchange/19_MsgLiquidatePosition.py +++ b/examples/chain_client/exchange/19_MsgLiquidatePosition.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,19 +37,21 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" cid = str(uuid.uuid4()) - order = composer.DerivativeOrder( + order = composer.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=39.01, # This should be the liquidation price - quantity=0.147, - leverage=1, + price=Decimal(39.01), # This should be the liquidation price + quantity=Decimal(0.147), + margin=composer.calculate_margin( + quantity=Decimal(0.147), price=Decimal(39.01), leverage=Decimal(1), is_reduce_only=False + ), + order_type="SELL", cid=cid, - is_buy=False, ) # prepare tx msg - msg = composer.MsgLiquidatePosition( + msg = composer.msg_liquidate_position( sender=address.to_acc_bech32(), subaccount_id="0x156df4d5bc8e7dd9191433e54bd6a11eeb390921000000000000000000000000", market_id=market_id, diff --git a/examples/chain_client/exchange/1_MsgDeposit.py b/examples/chain_client/exchange/1_MsgDeposit.py index 80b9f652..bbf64710 100644 --- a/examples/chain_client/exchange/1_MsgDeposit.py +++ b/examples/chain_client/exchange/1_MsgDeposit.py @@ -31,7 +31,9 @@ async def main() -> None: subaccount_id = address.get_subaccount_id(index=0) # prepare tx msg - msg = composer.MsgDeposit(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=0.000001, denom="INJ") + msg = composer.msg_deposit( + sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=0.000001, denom="INJ" + ) # build sim tx tx = ( diff --git a/examples/chain_client/13_MsgIncreasePositionMargin.py b/examples/chain_client/exchange/20_MsgIncreasePositionMargin.py similarity index 96% rename from examples/chain_client/13_MsgIncreasePositionMargin.py rename to examples/chain_client/exchange/20_MsgIncreasePositionMargin.py index 775a41e5..276276e7 100644 --- a/examples/chain_client/13_MsgIncreasePositionMargin.py +++ b/examples/chain_client/exchange/20_MsgIncreasePositionMargin.py @@ -1,5 +1,6 @@ import asyncio import os +from decimal import Decimal import dotenv from grpc import RpcError @@ -34,12 +35,12 @@ async def main() -> None: market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" # prepare tx msg - msg = composer.MsgIncreasePositionMargin( + msg = composer.msg_increase_position_margin( sender=address.to_acc_bech32(), market_id=market_id, source_subaccount_id=subaccount_id, destination_subaccount_id=subaccount_id, - amount=2, + amount=Decimal(2), ) # build sim tx diff --git a/examples/chain_client/exchange/12_MsgRewardsOptOut.py b/examples/chain_client/exchange/21_MsgRewardsOptOut.py similarity index 97% rename from examples/chain_client/exchange/12_MsgRewardsOptOut.py rename to examples/chain_client/exchange/21_MsgRewardsOptOut.py index 8beaa1f4..2306b541 100644 --- a/examples/chain_client/exchange/12_MsgRewardsOptOut.py +++ b/examples/chain_client/exchange/21_MsgRewardsOptOut.py @@ -30,7 +30,7 @@ async def main() -> None: await client.fetch_account(address.to_acc_bech32()) # prepare tx msg - msg = composer.MsgRewardsOptOut(sender=address.to_acc_bech32()) + msg = composer.msg_rewards_opt_out(sender=address.to_acc_bech32()) # build sim tx tx = ( diff --git a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py b/examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py similarity index 96% rename from examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py rename to examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py index 0f39dcdb..b638b28a 100644 --- a/examples/chain_client/34_MsgAdminUpdateBinaryOptionsMarket.py +++ b/examples/chain_client/exchange/22_MsgAdminUpdateBinaryOptionsMarket.py @@ -1,5 +1,6 @@ import asyncio import os +from decimal import Decimal import dotenv from grpc import RpcError @@ -32,12 +33,12 @@ async def main() -> None: # prepare trade info market_id = "0xfafec40a7b93331c1fc89c23f66d11fbb48f38dfdd78f7f4fc4031fad90f6896" status = "Demolished" - settlement_price = 1 + settlement_price = Decimal(1) expiration_timestamp = 1685460582 settlement_timestamp = 1690730982 # prepare tx msg - msg = composer.MsgAdminUpdateBinaryOptionsMarket( + msg = composer.msg_admin_update_binary_options_market( sender=address.to_acc_bech32(), market_id=market_id, settlement_price=settlement_price, diff --git a/examples/chain_client/exchange/9_MsgWithdraw.py b/examples/chain_client/exchange/2_MsgWithdraw.py similarity index 95% rename from examples/chain_client/exchange/9_MsgWithdraw.py rename to examples/chain_client/exchange/2_MsgWithdraw.py index b198c0aa..1070d28c 100644 --- a/examples/chain_client/exchange/9_MsgWithdraw.py +++ b/examples/chain_client/exchange/2_MsgWithdraw.py @@ -31,7 +31,7 @@ async def main() -> None: subaccount_id = address.get_subaccount_id(index=0) # prepare tx msg - msg = composer.MsgWithdraw(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom="USDT") + msg = composer.msg_withdraw(sender=address.to_acc_bech32(), subaccount_id=subaccount_id, amount=1, denom="USDT") # build sim tx tx = ( diff --git a/examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py b/examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py new file mode 100644 index 00000000..90a177ec --- /dev/null +++ b/examples/chain_client/exchange/3_MsgInstantSpotMarketLaunch.py @@ -0,0 +1,54 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + await client.initialize_tokens_from_chain_denoms() + composer = await client.composer() + await client.sync_timeout_height() + + message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( + network=network, + private_key=configured_private_key, + ) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + message = composer.msg_instant_spot_market_launch( + sender=address.to_acc_bech32(), + ticker="INJ/USDC", + base_denom="INJ", + quote_denom="USDC", + min_price_tick_size=Decimal("0.001"), + min_quantity_tick_size=Decimal("0.01"), + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py b/examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py new file mode 100644 index 00000000..b2b5dff4 --- /dev/null +++ b/examples/chain_client/exchange/4_MsgInstantPerpetualMarketLaunch.py @@ -0,0 +1,61 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + await client.initialize_tokens_from_chain_denoms() + composer = await client.composer() + await client.sync_timeout_height() + + message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( + network=network, + private_key=configured_private_key, + ) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + message = composer.msg_instant_perpetual_market_launch( + sender=address.to_acc_bech32(), + ticker="INJ/USDC PERP", + quote_denom="USDC", + oracle_base="INJ", + oracle_quote="USDC", + oracle_scale_factor=6, + oracle_type="Band", + maker_fee_rate=Decimal("-0.0001"), + taker_fee_rate=Decimal("0.001"), + initial_margin_ratio=Decimal("0.33"), + maintenance_margin_ratio=Decimal("0.095"), + min_price_tick_size=Decimal("0.001"), + min_quantity_tick_size=Decimal("0.01"), + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py b/examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py new file mode 100644 index 00000000..d451fd15 --- /dev/null +++ b/examples/chain_client/exchange/5_MsgInstantExpiryFuturesMarketLaunch.py @@ -0,0 +1,62 @@ +import asyncio +import os +from decimal import Decimal + +import dotenv + +from pyinjective.async_client import AsyncClient +from pyinjective.core.broadcaster import MsgBroadcasterWithPk +from pyinjective.core.network import Network +from pyinjective.wallet import PrivateKey + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + await client.initialize_tokens_from_chain_denoms() + composer = await client.composer() + await client.sync_timeout_height() + + message_broadcaster = MsgBroadcasterWithPk.new_using_simulation( + network=network, + private_key=configured_private_key, + ) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + # prepare tx msg + message = composer.msg_instant_expiry_futures_market_launch( + sender=address.to_acc_bech32(), + ticker="INJ/USDC FUT", + quote_denom="USDC", + oracle_base="INJ", + oracle_quote="USDC", + oracle_scale_factor=6, + oracle_type="Band", + expiry=2000000000, + maker_fee_rate=Decimal("-0.0001"), + taker_fee_rate=Decimal("0.001"), + initial_margin_ratio=Decimal("0.33"), + maintenance_margin_ratio=Decimal("0.095"), + min_price_tick_size=Decimal("0.001"), + min_quantity_tick_size=Decimal("0.01"), + ) + + # broadcast the transaction + result = await message_broadcaster.broadcast([message]) + print("---Transaction Response---") + print(result) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py similarity index 94% rename from examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py rename to examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py index d3ca5f16..5b3b966a 100644 --- a/examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py +++ b/examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -37,15 +38,14 @@ async def main() -> None: cid = str(uuid.uuid4()) # prepare tx msg - msg = composer.MsgCreateSpotLimitOrder( + msg = composer.msg_create_spot_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", cid=cid, ) diff --git a/examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py similarity index 94% rename from examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py rename to examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py index 5229632f..36ea27de 100644 --- a/examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py +++ b/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -36,14 +37,14 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.MsgCreateSpotMarketOrder( - sender=address.to_acc_bech32(), + msg = composer.msg_create_spot_market_order( market_id=market_id, + sender=address.to_acc_bech32(), subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=10.522, - quantity=0.01, - is_buy=True, + price=Decimal("10.522"), + quantity=Decimal("0.01"), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/exchange/5_MsgCancelSpotOrder.py b/examples/chain_client/exchange/8_MsgCancelSpotOrder.py similarity index 100% rename from examples/chain_client/exchange/5_MsgCancelSpotOrder.py rename to examples/chain_client/exchange/8_MsgCancelSpotOrder.py diff --git a/examples/chain_client/exchange/11_MsgBatchUpdateOrders.py b/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py similarity index 83% rename from examples/chain_client/exchange/11_MsgBatchUpdateOrders.py rename to examples/chain_client/exchange/9_MsgBatchUpdateOrders.py index 9efdc0a0..04e41058 100644 --- a/examples/chain_client/exchange/11_MsgBatchUpdateOrders.py +++ b/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py @@ -1,6 +1,7 @@ import asyncio import os import uuid +from decimal import Decimal import dotenv from grpc import RpcError @@ -43,12 +44,12 @@ async def main() -> None: spot_market_id_cancel_2 = "0x7a57e705bb4e09c88aecfc295569481dbf2fe1d5efe364651fbe72385938e9b0" derivative_orders_to_cancel = [ - composer.OrderData( + composer.order_data( market_id=derivative_market_id_cancel, subaccount_id=subaccount_id, order_hash="0x48690013c382d5dbaff9989db04629a16a5818d7524e027d517ccc89fd068103", ), - composer.OrderData( + composer.order_data( market_id=derivative_market_id_cancel_2, subaccount_id=subaccount_id, order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -56,12 +57,12 @@ async def main() -> None: ] spot_orders_to_cancel = [ - composer.OrderData( + composer.order_data( market_id=spot_market_id_cancel, subaccount_id=subaccount_id, cid="0e5c3ad5-2cc4-4a2a-bbe5-b12697739163", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id_cancel_2, subaccount_id=subaccount_id, order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", @@ -69,49 +70,49 @@ async def main() -> None: ] derivative_orders_to_create = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=derivative_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=25000, - quantity=0.1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(25000), + quantity=Decimal(0.1), + margin=composer.calculate_margin( + quantity=Decimal(0.1), price=Decimal(25000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.DerivativeOrder( + composer.derivative_order( market_id=derivative_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=50000, - quantity=0.01, - leverage=1, - is_buy=False, - is_po=False, + price=Decimal(50000), + quantity=Decimal(0.01), + margin=composer.calculate_margin( + quantity=Decimal(0.01), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False + ), + order_type="SELL", cid=str(uuid.uuid4()), ), ] spot_orders_to_create = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=3, - quantity=55, - is_buy=True, - is_po=False, + price=Decimal("3"), + quantity=Decimal("55"), + order_type="BUY", cid=str(uuid.uuid4()), ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id_create, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=300, - quantity=55, - is_buy=False, - is_po=False, + price=Decimal("300"), + quantity=Decimal("55"), + order_type="SELL", cid=str(uuid.uuid4()), ), ] diff --git a/examples/chain_client/41_MsgCreateInsuranceFund.py b/examples/chain_client/insurance/1_MsgCreateInsuranceFund.py similarity index 100% rename from examples/chain_client/41_MsgCreateInsuranceFund.py rename to examples/chain_client/insurance/1_MsgCreateInsuranceFund.py diff --git a/examples/chain_client/42_MsgUnderwrite.py b/examples/chain_client/insurance/2_MsgUnderwrite.py similarity index 100% rename from examples/chain_client/42_MsgUnderwrite.py rename to examples/chain_client/insurance/2_MsgUnderwrite.py diff --git a/examples/chain_client/43_MsgRequestRedemption.py b/examples/chain_client/insurance/3_MsgRequestRedemption.py similarity index 100% rename from examples/chain_client/43_MsgRequestRedemption.py rename to examples/chain_client/insurance/3_MsgRequestRedemption.py diff --git a/examples/chain_client/23_MsgRelayPriceFeedPrice.py b/examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py similarity index 100% rename from examples/chain_client/23_MsgRelayPriceFeedPrice.py rename to examples/chain_client/oracle/1_MsgRelayPriceFeedPrice.py diff --git a/examples/chain_client/36_MsgRelayProviderPrices.py b/examples/chain_client/oracle/2_MsgRelayProviderPrices.py similarity index 100% rename from examples/chain_client/36_MsgRelayProviderPrices.py rename to examples/chain_client/oracle/2_MsgRelayProviderPrices.py diff --git a/examples/chain_client/22_MsgSendToEth.py b/examples/chain_client/peggy/1_MsgSendToEth.py similarity index 100% rename from examples/chain_client/22_MsgSendToEth.py rename to examples/chain_client/peggy/1_MsgSendToEth.py diff --git a/examples/chain_client/25_MsgDelegate.py b/examples/chain_client/staking/1_MsgDelegate.py similarity index 100% rename from examples/chain_client/25_MsgDelegate.py rename to examples/chain_client/staking/1_MsgDelegate.py diff --git a/examples/chain_client/71_CreateDenom.py b/examples/chain_client/tokenfactory/1_CreateDenom.py similarity index 100% rename from examples/chain_client/71_CreateDenom.py rename to examples/chain_client/tokenfactory/1_CreateDenom.py diff --git a/examples/chain_client/72_MsgMint.py b/examples/chain_client/tokenfactory/2_MsgMint.py similarity index 100% rename from examples/chain_client/72_MsgMint.py rename to examples/chain_client/tokenfactory/2_MsgMint.py diff --git a/examples/chain_client/73_MsgBurn.py b/examples/chain_client/tokenfactory/3_MsgBurn.py similarity index 100% rename from examples/chain_client/73_MsgBurn.py rename to examples/chain_client/tokenfactory/3_MsgBurn.py diff --git a/examples/chain_client/75_MsgChangeAdmin.py b/examples/chain_client/tokenfactory/4_MsgChangeAdmin.py similarity index 100% rename from examples/chain_client/75_MsgChangeAdmin.py rename to examples/chain_client/tokenfactory/4_MsgChangeAdmin.py diff --git a/examples/chain_client/74_MsgSetDenomMetadata.py b/examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py similarity index 100% rename from examples/chain_client/74_MsgSetDenomMetadata.py rename to examples/chain_client/tokenfactory/5_MsgSetDenomMetadata.py diff --git a/examples/chain_client/68_DenomAuthorityMetadata.py b/examples/chain_client/tokenfactory/query/1_DenomAuthorityMetadata.py similarity index 100% rename from examples/chain_client/68_DenomAuthorityMetadata.py rename to examples/chain_client/tokenfactory/query/1_DenomAuthorityMetadata.py diff --git a/examples/chain_client/69_DenomsFromCreator.py b/examples/chain_client/tokenfactory/query/2_DenomsFromCreator.py similarity index 100% rename from examples/chain_client/69_DenomsFromCreator.py rename to examples/chain_client/tokenfactory/query/2_DenomsFromCreator.py diff --git a/examples/chain_client/70_TokenfactoryModuleState.py b/examples/chain_client/tokenfactory/query/3_TokenfactoryModuleState.py similarity index 100% rename from examples/chain_client/70_TokenfactoryModuleState.py rename to examples/chain_client/tokenfactory/query/3_TokenfactoryModuleState.py diff --git a/examples/chain_client/37_GetTx.py b/examples/chain_client/tx/query/1_GetTx.py similarity index 100% rename from examples/chain_client/37_GetTx.py rename to examples/chain_client/tx/query/1_GetTx.py diff --git a/examples/chain_client/40_MsgExecuteContract.py b/examples/chain_client/wasm/1_MsgExecuteContract.py similarity index 100% rename from examples/chain_client/40_MsgExecuteContract.py rename to examples/chain_client/wasm/1_MsgExecuteContract.py diff --git a/examples/chain_client/67_ContractsByCreator.py b/examples/chain_client/wasm/query/10_ContractsByCreator.py similarity index 100% rename from examples/chain_client/67_ContractsByCreator.py rename to examples/chain_client/wasm/query/10_ContractsByCreator.py diff --git a/examples/chain_client/58_ContractInfo.py b/examples/chain_client/wasm/query/1_ContractInfo.py similarity index 100% rename from examples/chain_client/58_ContractInfo.py rename to examples/chain_client/wasm/query/1_ContractInfo.py diff --git a/examples/chain_client/59_ContractHistory.py b/examples/chain_client/wasm/query/2_ContractHistory.py similarity index 100% rename from examples/chain_client/59_ContractHistory.py rename to examples/chain_client/wasm/query/2_ContractHistory.py diff --git a/examples/chain_client/60_ContractsByCode.py b/examples/chain_client/wasm/query/3_ContractsByCode.py similarity index 100% rename from examples/chain_client/60_ContractsByCode.py rename to examples/chain_client/wasm/query/3_ContractsByCode.py diff --git a/examples/chain_client/61_AllContractsState.py b/examples/chain_client/wasm/query/4_AllContractsState.py similarity index 100% rename from examples/chain_client/61_AllContractsState.py rename to examples/chain_client/wasm/query/4_AllContractsState.py diff --git a/examples/chain_client/62_RawContractState.py b/examples/chain_client/wasm/query/5_RawContractState.py similarity index 100% rename from examples/chain_client/62_RawContractState.py rename to examples/chain_client/wasm/query/5_RawContractState.py diff --git a/examples/chain_client/63_SmartContractState.py b/examples/chain_client/wasm/query/6_SmartContractState.py similarity index 100% rename from examples/chain_client/63_SmartContractState.py rename to examples/chain_client/wasm/query/6_SmartContractState.py diff --git a/examples/chain_client/64_SmartContractCode.py b/examples/chain_client/wasm/query/7_SmartContractCode.py similarity index 100% rename from examples/chain_client/64_SmartContractCode.py rename to examples/chain_client/wasm/query/7_SmartContractCode.py diff --git a/examples/chain_client/65_SmartContractCodes.py b/examples/chain_client/wasm/query/8_SmartContractCodes.py similarity index 100% rename from examples/chain_client/65_SmartContractCodes.py rename to examples/chain_client/wasm/query/8_SmartContractCodes.py diff --git a/examples/chain_client/66_SmartContractPinnedCodes.py b/examples/chain_client/wasm/query/9_SmartContractPinnedCodes.py similarity index 100% rename from examples/chain_client/66_SmartContractPinnedCodes.py rename to examples/chain_client/wasm/query/9_SmartContractPinnedCodes.py diff --git a/pyinjective/composer.py b/pyinjective/composer.py index df353d6b..9a0807c9 100644 --- a/pyinjective/composer.py +++ b/pyinjective/composer.py @@ -13,7 +13,7 @@ from pyinjective.core.token import Token from pyinjective.proto.cosmos.authz.v1beta1 import authz_pb2 as cosmos_authz_pb, tx_pb2 as cosmos_authz_tx_pb from pyinjective.proto.cosmos.bank.v1beta1 import bank_pb2 as bank_pb, tx_pb2 as cosmos_bank_tx_pb -from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as cosmos_dot_base_dot_v1beta1_dot_coin__pb2 +from pyinjective.proto.cosmos.base.v1beta1 import coin_pb2 as base_coin_pb from pyinjective.proto.cosmos.distribution.v1beta1 import ( distribution_pb2 as cosmos_distribution_pb2, tx_pb2 as cosmos_distribution_tx_pb, @@ -25,15 +25,19 @@ from pyinjective.proto.injective.auction.v1beta1 import tx_pb2 as injective_auction_tx_pb from pyinjective.proto.injective.exchange.v1beta1 import ( authz_pb2 as injective_authz_pb, - exchange_pb2 as injective_dot_exchange_dot_v1beta1_dot_exchange__pb2, + exchange_pb2 as injective_exchange_pb, tx_pb2 as injective_exchange_tx_pb, ) from pyinjective.proto.injective.insurance.v1beta1 import tx_pb2 as injective_insurance_tx_pb -from pyinjective.proto.injective.oracle.v1beta1 import tx_pb2 as injective_oracle_tx_pb +from pyinjective.proto.injective.oracle.v1beta1 import ( + oracle_pb2 as injective_oracle_pb, + tx_pb2 as injective_oracle_tx_pb, +) from pyinjective.proto.injective.peggy.v1 import msgs_pb2 as injective_peggy_tx_pb from pyinjective.proto.injective.stream.v1beta1 import query_pb2 as chain_stream_query from pyinjective.proto.injective.tokenfactory.v1beta1 import tx_pb2 as token_factory_tx_pb from pyinjective.proto.injective.wasmx.v1 import tx_pb2 as wasmx_tx_pb +from pyinjective.utils.denom import Denom REQUEST_TO_RESPONSE_TYPE_MAP = { "MsgCreateSpotLimitOrder": injective_exchange_tx_pb.MsgCreateSpotLimitOrderResponse, @@ -137,14 +141,14 @@ def Coin(self, amount: int, denom: str): This method is deprecated and will be removed soon. Please use `coin` instead """ warn("This method is deprecated. Use coin instead", DeprecationWarning, stacklevel=2) - return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=str(amount), denom=denom) + return base_coin_pb.Coin(amount=str(amount), denom=denom) def coin(self, amount: int, denom: str): """ This method create an instance of Coin gRPC type, considering the amount is already expressed in chain format """ formatted_amount_string = str(int(amount)) - return cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin(amount=formatted_amount_string, denom=denom) + return base_coin_pb.Coin(amount=formatted_amount_string, denom=denom) def create_coin_amount(self, amount: Decimal, token_name: str): """ @@ -154,35 +158,38 @@ def create_coin_amount(self, amount: Decimal, token_name: str): chain_amount = token.chain_formatted_value(human_readable_value=amount) return self.coin(amount=int(chain_amount), denom=token.denom) - def get_order_mask(self, **kwargs): - order_mask = 0 - - if kwargs.get("is_conditional"): - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.CONDITIONAL - else: - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.REGULAR - - if kwargs.get("order_direction") == "buy": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.DIRECTION_BUY_OR_HIGHER - - elif kwargs.get("order_direction") == "sell": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.DIRECTION_SELL_OR_LOWER - - if kwargs.get("order_type") == "market": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.TYPE_MARKET - - elif kwargs.get("order_type") == "limit": - order_mask += injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderMask.TYPE_LIMIT - - if order_mask == 0: - order_mask = 1 - - return order_mask - def OrderData( self, market_id: str, subaccount_id: str, order_hash: Optional[str] = None, cid: Optional[str] = None, **kwargs ): - order_mask = self.get_order_mask(**kwargs) + """ + This method is deprecated and will be removed soon. Please use `order_data` instead + """ + warn("This method is deprecated. Use order_data instead", DeprecationWarning, stacklevel=2) + + is_conditional = kwargs.get("is_conditional", False) + is_buy = kwargs.get("order_direction", "buy") == "buy" + is_market_order = kwargs.get("order_type", "limit") == "market" + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) + + return injective_exchange_tx_pb.OrderData( + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + order_mask=order_mask, + cid=cid, + ) + + def order_data( + self, + market_id: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + is_conditional: Optional[bool] = False, + is_buy: Optional[bool] = False, + is_market_order: Optional[bool] = False, + ) -> injective_exchange_tx_pb.OrderData: + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) return injective_exchange_tx_pb.OrderData( market_id=market_id, @@ -202,6 +209,11 @@ def SpotOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `spot_order` instead + """ + warn("This method is deprecated. Use spot_order instead", DeprecationWarning, stacklevel=2) + market = self.spot_markets[market_id] # prepare values @@ -210,20 +222,20 @@ def SpotOrder( trigger_price = market.price_to_chain_format(human_readable_value=Decimal(0)) if kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY + order_type = injective_exchange_pb.OrderType.BUY elif not kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL + order_type = injective_exchange_pb.OrderType.SELL elif kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY_PO + order_type = injective_exchange_pb.OrderType.BUY_PO elif not kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL_PO + order_type = injective_exchange_pb.OrderType.SELL_PO - return injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.SpotOrder( + return injective_exchange_pb.SpotOrder( market_id=market_id, - order_info=injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderInfo( + order_info=injective_exchange_pb.OrderInfo( subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=str(int(price)), @@ -234,6 +246,50 @@ def SpotOrder( trigger_price=str(int(trigger_price)), ) + def spot_order( + self, + market_id: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_pb.SpotOrder: + market = self.spot_markets[market_id] + + chain_quantity = f"{market.quantity_to_chain_format(human_readable_value=quantity).normalize():f}" + chain_price = f"{market.price_to_chain_format(human_readable_value=price).normalize():f}" + + trigger_price = trigger_price or Decimal(0) + chain_trigger_price = f"{market.price_to_chain_format(human_readable_value=trigger_price).normalize():f}" + + chain_order_type = injective_exchange_pb.OrderType.Value(order_type) + + return injective_exchange_pb.SpotOrder( + market_id=market_id, + order_info=injective_exchange_pb.OrderInfo( + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=chain_price, + quantity=chain_quantity, + cid=cid, + ), + order_type=chain_order_type, + trigger_price=chain_trigger_price, + ) + + def calculate_margin( + self, quantity: Decimal, price: Decimal, leverage: Decimal, is_reduce_only: bool = False + ) -> Decimal: + if is_reduce_only: + margin = Decimal(0) + else: + margin = quantity * price / leverage + + return margin + def DerivativeOrder( self, market_id: str, @@ -245,6 +301,10 @@ def DerivativeOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `derivative_order` instead + """ + warn("This method is deprecated. Use derivative_order instead", DeprecationWarning, stacklevel=2) market = self.derivative_markets[market_id] if kwargs.get("is_reduce_only", False): @@ -262,32 +322,32 @@ def DerivativeOrder( trigger_price = market.price_to_chain_format(human_readable_value=Decimal(str(trigger_price))) if kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY + order_type = injective_exchange_pb.OrderType.BUY elif not kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL + order_type = injective_exchange_pb.OrderType.SELL elif kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY_PO + order_type = injective_exchange_pb.OrderType.BUY_PO elif not kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL_PO + order_type = injective_exchange_pb.OrderType.SELL_PO elif kwargs.get("stop_buy"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.STOP_BUY + order_type = injective_exchange_pb.OrderType.STOP_BUY elif kwargs.get("stop_sell"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.STOP_SEll + order_type = injective_exchange_pb.OrderType.STOP_SEll elif kwargs.get("take_buy"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.TAKE_BUY + order_type = injective_exchange_pb.OrderType.TAKE_BUY elif kwargs.get("take_sell"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.TAKE_SELL + order_type = injective_exchange_pb.OrderType.TAKE_SELL - return injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.DerivativeOrder( + return injective_exchange_pb.DerivativeOrder( market_id=market_id, - order_info=injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderInfo( + order_info=injective_exchange_pb.OrderInfo( subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=str(int(price)), @@ -299,60 +359,121 @@ def DerivativeOrder( trigger_price=str(int(trigger_price)), ) - def BinaryOptionsOrder( + def derivative_order( self, market_id: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, cid: Optional[str] = None, - **kwargs, - ): - market = self.binary_option_markets[market_id] - denom = kwargs.get("denom", None) + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_pb.DerivativeOrder: + market = self.derivative_markets[market_id] - if kwargs.get("is_reduce_only", False): - margin = 0 - else: - margin = market.calculate_margin_in_chain_format( - human_readable_quantity=Decimal(str(quantity)), - human_readable_price=Decimal(str(price)), - is_buy=kwargs["is_buy"], - special_denom=denom, - ) + chain_quantity = market.quantity_to_chain_format(human_readable_value=quantity) + chain_price = market.price_to_chain_format(human_readable_value=price) + chain_margin = market.margin_to_chain_format(human_readable_value=margin) - # prepare values - price = market.price_to_chain_format(human_readable_value=Decimal(str(price)), special_denom=denom) - trigger_price = market.price_to_chain_format(human_readable_value=Decimal(str(0)), special_denom=denom) - quantity = market.quantity_to_chain_format(human_readable_value=Decimal(str(quantity)), special_denom=denom) + trigger_price = trigger_price or Decimal(0) + chain_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price) - if kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY + return self._basic_derivative_order( + market_id=market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + chain_price=chain_price, + chain_quantity=chain_quantity, + chain_margin=chain_margin, + order_type=order_type, + cid=cid, + chain_trigger_price=chain_trigger_price, + ) - elif not kwargs.get("is_buy") and not kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL + def binary_options_order( + self, + market_id: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + denom: Optional[Denom] = None, + ) -> injective_exchange_pb.DerivativeOrder: + market = self.binary_option_markets[market_id] - elif kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.BUY_PO + chain_quantity = market.quantity_to_chain_format(human_readable_value=quantity, special_denom=denom) + chain_price = market.price_to_chain_format(human_readable_value=price, special_denom=denom) + chain_margin = market.margin_to_chain_format(human_readable_value=margin, special_denom=denom) - elif not kwargs.get("is_buy") and kwargs.get("is_po"): - order_type = injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderType.SELL_PO + trigger_price = trigger_price or Decimal(0) + chain_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price, special_denom=denom) - return injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.DerivativeOrder( - market_id=market_id, - order_info=injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.OrderInfo( - subaccount_id=subaccount_id, - fee_recipient=fee_recipient, - price=str(int(price)), - quantity=str(int(quantity)), - cid=cid, - ), - margin=str(int(margin)), + return self._basic_derivative_order( + market_id=market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + chain_price=chain_price, + chain_quantity=chain_quantity, + chain_margin=chain_margin, order_type=order_type, - trigger_price=str(int(trigger_price)), + cid=cid, + chain_trigger_price=chain_trigger_price, + ) + + # region Auction module + def MsgBid(self, sender: str, bid_amount: float, round: float): + be_amount = Decimal(str(bid_amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_auction_tx_pb.MsgBid( + sender=sender, + round=round, + bid_amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), + ) + + # endregion + + # region Authz module + def MsgGrantGeneric(self, granter: str, grantee: str, msg_type: str, expire_in: int): + auth = cosmos_authz_pb.GenericAuthorization(msg=msg_type) + any_auth = any_pb2.Any() + any_auth.Pack(auth, type_url_prefix="") + + grant = cosmos_authz_pb.Grant( + authorization=any_auth, + expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), + ) + + return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + + def MsgExec(self, grantee: str, msgs: List): + any_msgs: List[any_pb2.Any] = [] + for msg in msgs: + any_msg = any_pb2.Any() + any_msg.Pack(msg, type_url_prefix="") + any_msgs.append(any_msg) + + return cosmos_authz_tx_pb.MsgExec(grantee=grantee, msgs=any_msgs) + + def MsgRevoke(self, granter: str, grantee: str, msg_type: str): + return cosmos_authz_tx_pb.MsgRevoke(granter=granter, grantee=grantee, msg_type_url=msg_type) + + def msg_execute_contract_compat(self, sender: str, contract: str, msg: str, funds: str): + return wasmx_tx_pb.MsgExecuteContractCompat( + sender=sender, + contract=contract, + msg=msg, + funds=funds, ) + # endregion + + # region Bank module def MsgSend(self, from_address: str, to_address: str, amount: float, denom: str): coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) @@ -362,16 +483,14 @@ def MsgSend(self, from_address: str, to_address: str, amount: float, denom: str) amount=[coin], ) - def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): - return wasm_tx_pb.MsgExecuteContract( - sender=sender, - contract=contract, - msg=bytes(msg, "utf-8"), - funds=kwargs.get("funds") # funds is a list of cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin. - # The coins in the list must be sorted in alphabetical order by denoms. - ) + # endregion + # region Chain Exchange module def MsgDeposit(self, sender: str, subaccount_id: str, amount: float, denom: str): + """ + This method is deprecated and will be removed soon. Please use `msg_deposit` instead + """ + warn("This method is deprecated. Use msg_deposit instead", DeprecationWarning, stacklevel=2) coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgDeposit( @@ -380,6 +499,153 @@ def MsgDeposit(self, sender: str, subaccount_id: str, amount: float, denom: str) amount=coin, ) + def msg_deposit(self, sender: str, subaccount_id: str, amount: Decimal, denom: str): + coin = self.create_coin_amount(amount=amount, token_name=denom) + + return injective_exchange_tx_pb.MsgDeposit( + sender=sender, + subaccount_id=subaccount_id, + amount=coin, + ) + + def MsgWithdraw(self, sender: str, subaccount_id: str, amount: float, denom: str): + """ + This method is deprecated and will be removed soon. Please use `msg_withdraw` instead + """ + warn("This method is deprecated. Use msg_withdraw instead", DeprecationWarning, stacklevel=2) + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + + return injective_exchange_tx_pb.MsgWithdraw( + sender=sender, + subaccount_id=subaccount_id, + amount=be_amount, + ) + + def msg_withdraw(self, sender: str, subaccount_id: str, amount: Decimal, denom: str): + be_amount = self.create_coin_amount(amount=amount, token_name=denom) + + return injective_exchange_tx_pb.MsgWithdraw( + sender=sender, + subaccount_id=subaccount_id, + amount=be_amount, + ) + + def msg_instant_spot_market_launch( + self, + sender: str, + ticker: str, + base_denom: str, + quote_denom: str, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantSpotMarketLaunch: + base_token = self.tokens[base_denom] + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals - base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal( + f"1e{base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + + return injective_exchange_tx_pb.MsgInstantSpotMarketLaunch( + sender=sender, + ticker=ticker, + base_denom=base_token.denom, + quote_denom=quote_token.denom, + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", + ) + + def msg_instant_perpetual_market_launch( + self, + sender: str, + ticker: str, + quote_denom: str, + oracle_base: str, + oracle_quote: str, + oracle_scale_factor: int, + oracle_type: str, + maker_fee_rate: Decimal, + taker_fee_rate: Decimal, + initial_margin_ratio: Decimal, + maintenance_margin_ratio: Decimal, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch: + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch( + sender=sender, + ticker=ticker, + quote_denom=quote_token.denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=injective_oracle_pb.OracleType.Value(oracle_type), + maker_fee_rate=f"{chain_maker_fee_rate.normalize():f}", + taker_fee_rate=f"{chain_taker_fee_rate.normalize():f}", + initial_margin_ratio=f"{chain_initial_margin_ratio.normalize():f}", + maintenance_margin_ratio=f"{chain_maintenance_margin_ratio.normalize():f}", + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", + ) + + def msg_instant_expiry_futures_market_launch( + self, + sender: str, + ticker: str, + quote_denom: str, + oracle_base: str, + oracle_quote: str, + oracle_scale_factor: int, + oracle_type: str, + expiry: int, + maker_fee_rate: Decimal, + taker_fee_rate: Decimal, + initial_margin_ratio: Decimal, + maintenance_margin_ratio: Decimal, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch: + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_exchange_tx_pb.MsgInstantExpiryFuturesMarketLaunch( + sender=sender, + ticker=ticker, + quote_denom=quote_token.denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=injective_oracle_pb.OracleType.Value(oracle_type), + expiry=expiry, + maker_fee_rate=f"{chain_maker_fee_rate.normalize():f}", + taker_fee_rate=f"{chain_taker_fee_rate.normalize():f}", + initial_margin_ratio=f"{chain_initial_margin_ratio.normalize():f}", + maintenance_margin_ratio=f"{chain_maintenance_margin_ratio.normalize():f}", + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", + ) + def MsgCreateSpotLimitOrder( self, market_id: str, @@ -391,52 +657,151 @@ def MsgCreateSpotLimitOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `msg_create_spot_limit_order` instead + """ + warn("This method is deprecated. Use msg_create_spot_limit_order instead", DeprecationWarning, stacklevel=2) + + order_type_name = "BUY" + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + return injective_exchange_tx_pb.MsgCreateSpotLimitOrder( sender=sender, - order=self.SpotOrder( + order=self.spot_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=price, - quantity=quantity, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + order_type=order_type_name, cid=cid, - **kwargs, ), ) - def MsgCreateSpotMarketOrder( + def msg_create_spot_limit_order( self, market_id: str, sender: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, - is_buy: bool, + price: Decimal, + quantity: Decimal, + order_type: str, cid: Optional[str] = None, - ): - return injective_exchange_tx_pb.MsgCreateSpotMarketOrder( + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateSpotLimitOrder: + return injective_exchange_tx_pb.MsgCreateSpotLimitOrder( sender=sender, - order=self.SpotOrder( + order=self.spot_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=price, quantity=quantity, - is_buy=is_buy, + order_type=order_type, cid=cid, + trigger_price=trigger_price, ), ) - def MsgCancelSpotOrder( + def MsgBatchCreateSpotLimitOrders(self, sender: str, orders: List): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_create_spot_limit_orders` instead + """ + warn( + "This method is deprecated. Use msg_batch_create_spot_limit_orders instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders(sender=sender, orders=orders) + + def msg_batch_create_spot_limit_orders( + self, sender: str, orders: List[injective_exchange_pb.SpotOrder] + ) -> injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders: + return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders(sender=sender, orders=orders) + + def MsgCreateSpotMarketOrder( self, market_id: str, sender: str, subaccount_id: str, - order_hash: Optional[str] = None, + fee_recipient: str, + price: float, + quantity: float, + is_buy: bool, cid: Optional[str] = None, ): - return injective_exchange_tx_pb.MsgCancelSpotOrder( + """ + This method is deprecated and will be removed soon. Please use `msg_create_spot_market_order` instead + """ + warn("This method is deprecated. Use msg_create_spot_market_order instead", DeprecationWarning, stacklevel=2) + + order_type_name = "BUY" + if not is_buy: + order_type_name = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + return injective_exchange_tx_pb.MsgCreateSpotMarketOrder( + sender=sender, + order=self.spot_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + order_type=order_type_name, + cid=cid, + ), + ) + + def msg_create_spot_market_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateSpotMarketOrder: + return injective_exchange_tx_pb.MsgCreateSpotMarketOrder( + sender=sender, + order=self.spot_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ), + ) + + def MsgCancelSpotOrder( + self, + market_id: str, + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_cancel_spot_order` instead + """ + warn("This method is deprecated. Use msg_cancel_spot_order instead", DeprecationWarning, stacklevel=2) + return injective_exchange_tx_pb.MsgCancelSpotOrder( sender=sender, market_id=market_id, subaccount_id=subaccount_id, @@ -444,14 +809,111 @@ def MsgCancelSpotOrder( cid=cid, ) - def MsgBatchCreateSpotLimitOrders(self, sender: str, orders: List): - return injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders(sender=sender, orders=orders) + def msg_cancel_spot_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + ) -> injective_exchange_tx_pb.MsgCancelSpotOrder: + return injective_exchange_tx_pb.MsgCancelSpotOrder( + sender=sender, + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + ) def MsgBatchCancelSpotOrders(self, sender: str, data: List): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_cancel_spot_orders` instead + """ + warn("This method is deprecated. Use msg_batch_cancel_spot_orders instead", DeprecationWarning, stacklevel=2) return injective_exchange_tx_pb.MsgBatchCancelSpotOrders(sender=sender, data=data) - def MsgRewardsOptOut(self, sender: str): - return injective_exchange_tx_pb.MsgRewardsOptOut(sender=sender) + def msg_batch_cancel_spot_orders( + self, sender: str, orders_data: List[injective_exchange_tx_pb.OrderData] + ) -> injective_exchange_tx_pb.MsgBatchCancelSpotOrders: + return injective_exchange_tx_pb.MsgBatchCancelSpotOrders(sender=sender, data=orders_data) + + def MsgBatchUpdateOrders(self, sender: str, **kwargs): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_update_orders` instead + """ + warn("This method is deprecated. Use msg_batch_update_orders instead", DeprecationWarning, stacklevel=2) + return injective_exchange_tx_pb.MsgBatchUpdateOrders( + sender=sender, + subaccount_id=kwargs.get("subaccount_id"), + spot_market_ids_to_cancel_all=kwargs.get("spot_market_ids_to_cancel_all"), + derivative_market_ids_to_cancel_all=kwargs.get("derivative_market_ids_to_cancel_all"), + spot_orders_to_cancel=kwargs.get("spot_orders_to_cancel"), + derivative_orders_to_cancel=kwargs.get("derivative_orders_to_cancel"), + spot_orders_to_create=kwargs.get("spot_orders_to_create"), + derivative_orders_to_create=kwargs.get("derivative_orders_to_create"), + binary_options_orders_to_cancel=kwargs.get("binary_options_orders_to_cancel"), + binary_options_market_ids_to_cancel_all=kwargs.get("binary_options_market_ids_to_cancel_all"), + binary_options_orders_to_create=kwargs.get("binary_options_orders_to_create"), + ) + + def msg_batch_update_orders( + self, + sender: str, + subaccount_id: Optional[str] = None, + spot_market_ids_to_cancel_all: Optional[List[str]] = None, + derivative_market_ids_to_cancel_all: Optional[List[str]] = None, + spot_orders_to_cancel: Optional[List[injective_exchange_tx_pb.OrderData]] = None, + derivative_orders_to_cancel: Optional[List[injective_exchange_tx_pb.OrderData]] = None, + spot_orders_to_create: Optional[List[injective_exchange_pb.SpotOrder]] = None, + derivative_orders_to_create: Optional[List[injective_exchange_pb.DerivativeOrder]] = None, + binary_options_orders_to_cancel: Optional[List[injective_exchange_tx_pb.OrderData]] = None, + binary_options_market_ids_to_cancel_all: Optional[List[str]] = None, + binary_options_orders_to_create: Optional[List[injective_exchange_pb.DerivativeOrder]] = None, + ) -> injective_exchange_tx_pb.MsgBatchUpdateOrders: + return injective_exchange_tx_pb.MsgBatchUpdateOrders( + sender=sender, + subaccount_id=subaccount_id, + spot_market_ids_to_cancel_all=spot_market_ids_to_cancel_all, + derivative_market_ids_to_cancel_all=derivative_market_ids_to_cancel_all, + spot_orders_to_cancel=spot_orders_to_cancel, + derivative_orders_to_cancel=derivative_orders_to_cancel, + spot_orders_to_create=spot_orders_to_create, + derivative_orders_to_create=derivative_orders_to_create, + binary_options_orders_to_cancel=binary_options_orders_to_cancel, + binary_options_market_ids_to_cancel_all=binary_options_market_ids_to_cancel_all, + binary_options_orders_to_create=binary_options_orders_to_create, + ) + + def MsgPrivilegedExecuteContract( + self, sender: str, contract: str, msg: str, **kwargs + ) -> injective_exchange_tx_pb.MsgPrivilegedExecuteContract: + """ + This method is deprecated and will be removed soon. Please use `msg_privileged_execute_contract` instead + """ + warn("This method is deprecated. Use msg_privileged_execute_contract instead", DeprecationWarning, stacklevel=2) + + return injective_exchange_tx_pb.MsgPrivilegedExecuteContract( + sender=sender, + contract_address=contract, + data=msg, + funds=kwargs.get("funds") # funds is a string of Coin strings, comma separated, + # e.g. 100000inj,20000000000usdt + ) + + def msg_privileged_execute_contract( + self, + sender: str, + contract_address: str, + data: str, + funds: Optional[str] = None, + ) -> injective_exchange_tx_pb.MsgPrivilegedExecuteContract: + # funds is a string of Coin strings, comma separated, e.g. 100000inj,20000000000usdt + return injective_exchange_tx_pb.MsgPrivilegedExecuteContract( + sender=sender, + contract_address=contract_address, + data=data, + funds=funds, + ) def MsgCreateDerivativeLimitOrder( self, @@ -464,46 +926,105 @@ def MsgCreateDerivativeLimitOrder( cid: Optional[str] = None, **kwargs, ): + """ + This method is deprecated and will be removed soon. Please use `msg_create_derivative_limit_order` instead + """ + warn( + "This method is deprecated. Use msg_create_derivative_limit_order instead", DeprecationWarning, stacklevel=2 + ) + + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) / Decimal(str(kwargs["leverage"])) + + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + return injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder( sender=sender, - order=self.DerivativeOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=price, - quantity=quantity, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, ), ) - def MsgCreateDerivativeMarketOrder( + def msg_create_derivative_limit_order( self, market_id: str, sender: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, - is_buy: bool, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, cid: Optional[str] = None, - **kwargs, - ): - return injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder( + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder: + return injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder( sender=sender, - order=self.DerivativeOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=price, quantity=quantity, - is_buy=is_buy, + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=trigger_price, ), ) - def MsgCreateBinaryOptionsLimitOrder( + def MsgBatchCreateDerivativeLimitOrders(self, sender: str, orders: List): + """ + This method is deprecated and will be removed soon. + Please use `msg_batch_create_derivative_limit_orders` instead + """ + warn( + "This method is deprecated. Use msg_batch_create_derivative_limit_orders instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders(sender=sender, orders=orders) + + def msg_batch_create_derivative_limit_orders( + self, + sender: str, + orders: List[injective_exchange_pb.DerivativeOrder], + ) -> injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders: + return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders(sender=sender, orders=orders) + + def MsgCreateDerivativeMarketOrder( self, market_id: str, sender: str, @@ -514,95 +1035,156 @@ def MsgCreateBinaryOptionsLimitOrder( cid: Optional[str] = None, **kwargs, ): - return injective_exchange_tx_pb.MsgCreateBinaryOptionsLimitOrder( + """ + This method is deprecated and will be removed soon. Please use `msg_create_derivative_market_order` instead + """ + warn( + "This method is deprecated. Use msg_create_derivative_market_order instead", + DeprecationWarning, + stacklevel=2, + ) + + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) / Decimal(str(kwargs["leverage"])) + + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + + return injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder( sender=sender, - order=self.BinaryOptionsOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=price, - quantity=quantity, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, ), ) - def MsgCreateBinaryOptionsMarketOrder( + def msg_create_derivative_market_order( self, market_id: str, sender: str, subaccount_id: str, fee_recipient: str, - price: float, - quantity: float, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, cid: Optional[str] = None, - **kwargs, - ): - return injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder( + trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder: + return injective_exchange_tx_pb.MsgCreateDerivativeMarketOrder( sender=sender, - order=self.BinaryOptionsOrder( + order=self.derivative_order( market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=price, quantity=quantity, + margin=margin, + order_type=order_type, cid=cid, - **kwargs, + trigger_price=trigger_price, ), ) - def MsgCancelBinaryOptionsOrder( + def MsgCancelDerivativeOrder( self, - sender: str, market_id: str, + sender: str, subaccount_id: str, order_hash: Optional[str] = None, cid: Optional[str] = None, + **kwargs, ): - return injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder( + """ + This method is deprecated and will be removed soon. Please use `msg_cancel_derivative_order` instead + """ + warn( + "This method is deprecated. Use msg_cancel_derivative_order instead", + DeprecationWarning, + stacklevel=2, + ) + + is_conditional = kwargs.get("is_conditional", False) + is_buy = kwargs.get("order_direction", "buy") == "buy" + is_market_order = kwargs.get("order_type", "limit") == "market" + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) + + return injective_exchange_tx_pb.MsgCancelDerivativeOrder( sender=sender, market_id=market_id, subaccount_id=subaccount_id, order_hash=order_hash, + order_mask=order_mask, cid=cid, ) - def MsgAdminUpdateBinaryOptionsMarket( + def msg_cancel_derivative_order( self, - sender: str, market_id: str, - status: str, - **kwargs, - ): - price_to_bytes = None - - if kwargs.get("settlement_price") is not None: - scale_price = Decimal((kwargs.get("settlement_price") * pow(10, 18))) - price_to_bytes = bytes(str(scale_price), "utf-8") - - else: - price_to_bytes = "" + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + is_conditional: Optional[bool] = False, + is_buy: Optional[bool] = False, + is_market_order: Optional[bool] = False, + ) -> injective_exchange_tx_pb.MsgCancelDerivativeOrder: + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) - return injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket( + return injective_exchange_tx_pb.MsgCancelDerivativeOrder( sender=sender, market_id=market_id, - settlement_price=price_to_bytes, - expiration_timestamp=kwargs.get("expiration_timestamp"), - settlement_timestamp=kwargs.get("settlement_timestamp"), - status=status, + subaccount_id=subaccount_id, + order_hash=order_hash, + order_mask=order_mask, + cid=cid, ) - def MsgRelayProviderPrices(self, sender: str, provider: str, symbols: list, prices: list): - oracle_prices = [] - - for price in prices: - scale_price = Decimal((price) * pow(10, 18)) - price_to_bytes = bytes(str(scale_price), "utf-8") - oracle_prices.append(price_to_bytes) - - return injective_oracle_tx_pb.MsgRelayProviderPrices( - sender=sender, provider=provider, symbols=symbols, prices=oracle_prices + def MsgBatchCancelDerivativeOrders(self, sender: str, data: List): + """ + This method is deprecated and will be removed soon. Please use `msg_batch_cancel_derivative_orders` instead + """ + warn( + "This method is deprecated. Use msg_batch_cancel_derivative_orders instead", + DeprecationWarning, + stacklevel=2, ) + return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders(sender=sender, data=data) + + def msg_batch_cancel_derivative_orders( + self, sender: str, orders_data: List[injective_exchange_tx_pb.OrderData] + ) -> injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders: + return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders(sender=sender, data=orders_data) def MsgInstantBinaryOptionsMarketLaunch( self, @@ -622,6 +1204,15 @@ def MsgInstantBinaryOptionsMarketLaunch( min_quantity_tick_size: float, **kwargs, ): + """ + This method is deprecated and will be removed soon. + Please use `msg_instant_binary_options_market_launch` instead + """ + warn( + "This method is deprecated. Use msg_instant_binary_options_market_launch instead", + DeprecationWarning, + stacklevel=2, + ) scaled_maker_fee_rate = Decimal((maker_fee_rate * pow(10, 18))) maker_fee_to_bytes = bytes(str(scaled_maker_fee_rate), "utf-8") @@ -651,75 +1242,281 @@ def MsgInstantBinaryOptionsMarketLaunch( admin=kwargs.get("admin"), ) - def MsgCancelDerivativeOrder( + def msg_instant_binary_options_market_launch( self, - market_id: str, sender: str, - subaccount_id: str, - order_hash: Optional[str] = None, - cid: Optional[str] = None, - **kwargs, - ): - order_mask = self.get_order_mask(**kwargs) - - return injective_exchange_tx_pb.MsgCancelDerivativeOrder( + ticker: str, + oracle_symbol: str, + oracle_provider: str, + oracle_type: str, + oracle_scale_factor: int, + maker_fee_rate: Decimal, + taker_fee_rate: Decimal, + expiration_timestamp: int, + settlement_timestamp: int, + admin: str, + quote_denom: str, + min_price_tick_size: Decimal, + min_quantity_tick_size: Decimal, + ) -> injective_exchange_tx_pb.MsgInstantPerpetualMarketLaunch: + quote_token = self.tokens[quote_denom] + + chain_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + chain_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + chain_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return injective_exchange_tx_pb.MsgInstantBinaryOptionsMarketLaunch( sender=sender, - market_id=market_id, - subaccount_id=subaccount_id, - order_hash=order_hash, - order_mask=order_mask, - cid=cid, + ticker=ticker, + oracle_symbol=oracle_symbol, + oracle_provider=oracle_provider, + oracle_type=injective_oracle_pb.OracleType.Value(oracle_type), + oracle_scale_factor=oracle_scale_factor, + maker_fee_rate=f"{chain_maker_fee_rate.normalize():f}", + taker_fee_rate=f"{chain_taker_fee_rate.normalize():f}", + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + admin=admin, + quote_denom=quote_token.denom, + min_price_tick_size=f"{chain_min_price_tick_size.normalize():f}", + min_quantity_tick_size=f"{chain_min_quantity_tick_size.normalize():f}", ) - def MsgBatchCreateDerivativeLimitOrders(self, sender: str, orders: List): - return injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders(sender=sender, orders=orders) + def MsgCreateBinaryOptionsLimitOrder( + self, + market_id: str, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: float, + quantity: float, + cid: Optional[str] = None, + **kwargs, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_create_binary_options_limit_order` instead + """ + warn( + "This method is deprecated. Use msg_create_binary_options_limit_order instead", + DeprecationWarning, + stacklevel=2, + ) + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) - def MsgBatchCancelDerivativeOrders(self, sender: str, data: List): - return injective_exchange_tx_pb.MsgBatchCancelDerivativeOrders(sender=sender, data=data) + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) - def MsgBatchUpdateOrders(self, sender: str, **kwargs): - return injective_exchange_tx_pb.MsgBatchUpdateOrders( + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + + return injective_exchange_tx_pb.MsgCreateBinaryOptionsLimitOrder( sender=sender, - subaccount_id=kwargs.get("subaccount_id"), - spot_market_ids_to_cancel_all=kwargs.get("spot_market_ids_to_cancel_all"), - derivative_market_ids_to_cancel_all=kwargs.get("derivative_market_ids_to_cancel_all"), - spot_orders_to_cancel=kwargs.get("spot_orders_to_cancel"), - derivative_orders_to_cancel=kwargs.get("derivative_orders_to_cancel"), - spot_orders_to_create=kwargs.get("spot_orders_to_create"), - derivative_orders_to_create=kwargs.get("derivative_orders_to_create"), - binary_options_orders_to_cancel=kwargs.get("binary_options_orders_to_cancel"), - binary_options_market_ids_to_cancel_all=kwargs.get("binary_options_market_ids_to_cancel_all"), - binary_options_orders_to_create=kwargs.get("binary_options_orders_to_create"), + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, + denom=kwargs.get("denom"), + ), ) - def MsgLiquidatePosition( + def msg_create_binary_options_limit_order( self, + market_id: str, sender: str, subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + denom: Optional[Denom] = None, + ) -> injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder: + return injective_exchange_tx_pb.MsgCreateDerivativeLimitOrder( + sender=sender, + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + denom=denom, + ), + ) + + def MsgCreateBinaryOptionsMarketOrder( + self, market_id: str, - order: Optional[injective_dot_exchange_dot_v1beta1_dot_exchange__pb2.DerivativeOrder] = None, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: float, + quantity: float, + cid: Optional[str] = None, + **kwargs, ): - return injective_exchange_tx_pb.MsgLiquidatePosition( - sender=sender, subaccount_id=subaccount_id, market_id=market_id, order=order + """ + This method is deprecated and will be removed soon. Please use `msg_create_binary_options_market_order` instead + """ + warn( + "This method is deprecated. Use msg_create_binary_options_market_order instead", + DeprecationWarning, + stacklevel=2, ) + if kwargs.get("is_reduce_only", False): + margin = Decimal(0) + else: + margin = Decimal(str(price)) * Decimal(str(quantity)) - def MsgIncreasePositionMargin( + if kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY) + + elif not kwargs.get("is_buy") and not kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL) + + elif kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.BUY_PO) + + elif not kwargs.get("is_buy") and kwargs.get("is_po"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.SELL_PO) + + elif kwargs.get("stop_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_BUY) + + elif kwargs.get("stop_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.STOP_SEll) + + elif kwargs.get("take_buy"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_BUY) + + elif kwargs.get("take_sell"): + order_type = injective_exchange_pb.OrderType.Name(injective_exchange_pb.OrderType.TAKE_SELL) + + return injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder( + sender=sender, + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=Decimal(str(price)), + quantity=Decimal(str(quantity)), + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=Decimal(str(kwargs["trigger_price"])) if "trigger_price" in kwargs else None, + denom=kwargs.get("denom"), + ), + ) + + def msg_create_binary_options_market_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + fee_recipient: str, + price: Decimal, + quantity: Decimal, + margin: Decimal, + order_type: str, + cid: Optional[str] = None, + trigger_price: Optional[Decimal] = None, + denom: Optional[Denom] = None, + ): + return injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder( + sender=sender, + order=self.binary_options_order( + market_id=market_id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + denom=denom, + ), + ) + + def MsgCancelBinaryOptionsOrder( self, sender: str, - source_subaccount_id: str, - destination_subaccount_id: str, market_id: str, - amount: float, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, ): - market = self.derivative_markets[market_id] + """ + This method is deprecated and will be removed soon. Please use `msg_cancel_binary_options_order` instead + """ + warn( + "This method is deprecated. Use msg_cancel_binary_options_order instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder( + sender=sender, + market_id=market_id, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + ) - additional_margin = market.margin_to_chain_format(human_readable_value=Decimal(str(amount))) - return injective_exchange_tx_pb.MsgIncreasePositionMargin( + def msg_cancel_binary_options_order( + self, + market_id: str, + sender: str, + subaccount_id: str, + order_hash: Optional[str] = None, + cid: Optional[str] = None, + is_conditional: Optional[bool] = False, + is_buy: Optional[bool] = False, + is_market_order: Optional[bool] = False, + ) -> injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder: + order_mask = self._order_mask(is_conditional=is_conditional, is_buy=is_buy, is_market_order=is_market_order) + + return injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder( sender=sender, - source_subaccount_id=source_subaccount_id, - destination_subaccount_id=destination_subaccount_id, market_id=market_id, - amount=str(int(additional_margin)), + subaccount_id=subaccount_id, + order_hash=order_hash, + order_mask=order_mask, + cid=cid, ) def MsgSubaccountTransfer( @@ -730,6 +1527,14 @@ def MsgSubaccountTransfer( amount: int, denom: str, ): + """ + This method is deprecated and will be removed soon. Please use `msg_subaccount_transfer` instead + """ + warn( + "This method is deprecated. Use msg_subaccount_transfer instead", + DeprecationWarning, + stacklevel=2, + ) be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgSubaccountTransfer( @@ -739,12 +1544,20 @@ def MsgSubaccountTransfer( amount=be_amount, ) - def MsgWithdraw(self, sender: str, subaccount_id: str, amount: float, denom: str): - be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + def msg_subaccount_transfer( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + amount: Decimal, + denom: str, + ) -> injective_exchange_tx_pb.MsgSubaccountTransfer: + be_amount = self.create_coin_amount(amount=amount, token_name=denom) - return injective_exchange_tx_pb.MsgWithdraw( + return injective_exchange_tx_pb.MsgSubaccountTransfer( sender=sender, - subaccount_id=subaccount_id, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, amount=be_amount, ) @@ -756,6 +1569,14 @@ def MsgExternalTransfer( amount: int, denom: str, ): + """ + This method is deprecated and will be removed soon. Please use `msg_external_transfer` instead + """ + warn( + "This method is deprecated. Use msg_external_transfer instead", + DeprecationWarning, + stacklevel=2, + ) coin = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) return injective_exchange_tx_pb.MsgExternalTransfer( @@ -765,129 +1586,184 @@ def MsgExternalTransfer( amount=coin, ) - def MsgBid(self, sender: str, bid_amount: float, round: float): - be_amount = Decimal(str(bid_amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + def msg_external_transfer( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + amount: Decimal, + denom: str, + ) -> injective_exchange_tx_pb.MsgExternalTransfer: + coin = self.create_coin_amount(amount=amount, token_name=denom) - return injective_auction_tx_pb.MsgBid( + return injective_exchange_tx_pb.MsgExternalTransfer( sender=sender, - round=round, - bid_amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=coin, ) - def MsgGrantGeneric(self, granter: str, grantee: str, msg_type: str, expire_in: int): - auth = cosmos_authz_pb.GenericAuthorization(msg=msg_type) - any_auth = any_pb2.Any() - any_auth.Pack(auth, type_url_prefix="") - - grant = cosmos_authz_pb.Grant( - authorization=any_auth, - expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), + def MsgLiquidatePosition( + self, + sender: str, + subaccount_id: str, + market_id: str, + order: Optional[injective_exchange_pb.DerivativeOrder] = None, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_liquidate_position` instead + """ + warn( + "This method is deprecated. Use msg_liquidate_position instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgLiquidatePosition( + sender=sender, subaccount_id=subaccount_id, market_id=market_id, order=order ) - return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + def msg_liquidate_position( + self, + sender: str, + subaccount_id: str, + market_id: str, + order: Optional[injective_exchange_pb.DerivativeOrder] = None, + ) -> injective_exchange_tx_pb.MsgLiquidatePosition: + return injective_exchange_tx_pb.MsgLiquidatePosition( + sender=sender, subaccount_id=subaccount_id, market_id=market_id, order=order + ) - def MsgGrantTyped( + def msg_emergency_settle_market( self, - granter: str, - grantee: str, - msg_type: str, - expire_in: int, + sender: str, subaccount_id: str, - **kwargs, + market_id: str, + ) -> injective_exchange_tx_pb.MsgEmergencySettleMarket: + return injective_exchange_tx_pb.MsgEmergencySettleMarket( + sender=sender, subaccount_id=subaccount_id, market_id=market_id + ) + + def MsgIncreasePositionMargin( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + market_id: str, + amount: float, ): - auth = None - if msg_type == "CreateSpotLimitOrderAuthz": - auth = injective_authz_pb.CreateSpotLimitOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CreateSpotMarketOrderAuthz": - auth = injective_authz_pb.CreateSpotMarketOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCreateSpotLimitOrdersAuthz": - auth = injective_authz_pb.BatchCreateSpotLimitOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CancelSpotOrderAuthz": - auth = injective_authz_pb.CancelSpotOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCancelSpotOrdersAuthz": - auth = injective_authz_pb.BatchCancelSpotOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CreateDerivativeLimitOrderAuthz": - auth = injective_authz_pb.CreateDerivativeLimitOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CreateDerivativeMarketOrderAuthz": - auth = injective_authz_pb.CreateDerivativeMarketOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCreateDerivativeLimitOrdersAuthz": - auth = injective_authz_pb.BatchCreateDerivativeLimitOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "CancelDerivativeOrderAuthz": - auth = injective_authz_pb.CancelDerivativeOrderAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchCancelDerivativeOrdersAuthz": - auth = injective_authz_pb.BatchCancelDerivativeOrdersAuthz( - subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") - ) - elif msg_type == "BatchUpdateOrdersAuthz": - auth = injective_authz_pb.BatchUpdateOrdersAuthz( - subaccount_id=subaccount_id, - spot_markets=kwargs.get("spot_markets"), - derivative_markets=kwargs.get("derivative_markets"), - ) + """ + This method is deprecated and will be removed soon. Please use `msg_increase_position_margin` instead + """ + warn( + "This method is deprecated. Use msg_increase_position_margin instead", + DeprecationWarning, + stacklevel=2, + ) + market = self.derivative_markets[market_id] - any_auth = any_pb2.Any() - any_auth.Pack(auth, type_url_prefix="") + additional_margin = market.margin_to_chain_format(human_readable_value=Decimal(str(amount))) + return injective_exchange_tx_pb.MsgIncreasePositionMargin( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + market_id=market_id, + amount=str(int(additional_margin)), + ) - grant = cosmos_authz_pb.Grant( - authorization=any_auth, - expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), + def msg_increase_position_margin( + self, + sender: str, + source_subaccount_id: str, + destination_subaccount_id: str, + market_id: str, + amount: Decimal, + ): + market = self.derivative_markets[market_id] + + additional_margin = market.margin_to_chain_format(human_readable_value=amount) + return injective_exchange_tx_pb.MsgIncreasePositionMargin( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + market_id=market_id, + amount=str(int(additional_margin)), ) - return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) - - def MsgExec(self, grantee: str, msgs: List): - any_msgs: List[any_pb2.Any] = [] - for msg in msgs: - any_msg = any_pb2.Any() - any_msg.Pack(msg, type_url_prefix="") - any_msgs.append(any_msg) + def MsgRewardsOptOut(self, sender: str): + """ + This method is deprecated and will be removed soon. Please use `msg_rewards_opt_out` instead + """ + warn( + "This method is deprecated. Use msg_rewards_opt_out instead", + DeprecationWarning, + stacklevel=2, + ) + return injective_exchange_tx_pb.MsgRewardsOptOut(sender=sender) - return cosmos_authz_tx_pb.MsgExec(grantee=grantee, msgs=any_msgs) + def msg_rewards_opt_out(self, sender: str) -> injective_exchange_tx_pb.MsgRewardsOptOut: + return injective_exchange_tx_pb.MsgRewardsOptOut(sender=sender) - def MsgRevoke(self, granter: str, grantee: str, msg_type: str): - return cosmos_authz_tx_pb.MsgRevoke(granter=granter, grantee=grantee, msg_type_url=msg_type) + def MsgAdminUpdateBinaryOptionsMarket( + self, + sender: str, + market_id: str, + status: str, + **kwargs, + ): + """ + This method is deprecated and will be removed soon. Please use `msg_admin_update_binary_options_market` instead + """ + warn( + "This method is deprecated. Use msg_admin_update_binary_options_market instead", + DeprecationWarning, + stacklevel=2, + ) - def MsgRelayPriceFeedPrice(self, sender: list, base: list, quote: list, price: list): - return injective_oracle_tx_pb.MsgRelayPriceFeedPrice(sender=sender, base=base, quote=quote, price=price) + if kwargs.get("settlement_price") is not None: + scale_price = Decimal((kwargs.get("settlement_price") * pow(10, 18))) + price_to_bytes = bytes(str(scale_price), "utf-8") - def MsgSendToEth(self, denom: str, sender: str, eth_dest: str, amount: float, bridge_fee: float): - be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) - be_bridge_fee = self.create_coin_amount(amount=Decimal(str(bridge_fee)), token_name=denom) + else: + price_to_bytes = "" - return injective_peggy_tx_pb.MsgSendToEth( + return injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket( sender=sender, - eth_dest=eth_dest, - amount=be_amount, - bridge_fee=be_bridge_fee, + market_id=market_id, + settlement_price=price_to_bytes, + expiration_timestamp=kwargs.get("expiration_timestamp"), + settlement_timestamp=kwargs.get("settlement_timestamp"), + status=status, ) - def MsgDelegate(self, delegator_address: str, validator_address: str, amount: float): - be_amount = Decimal(str(amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + def msg_admin_update_binary_options_market( + self, + sender: str, + market_id: str, + status: str, + settlement_price: Optional[Decimal] = None, + expiration_timestamp: Optional[int] = None, + settlement_timestamp: Optional[int] = None, + ) -> injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket: + market = self.binary_option_markets[market_id] - return cosmos_staking_tx_pb.MsgDelegate( - delegator_address=delegator_address, - validator_address=validator_address, - amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), + if settlement_price is not None: + chain_settlement_price = market.price_to_chain_format(human_readable_value=settlement_price) + price_parameter = f"{chain_settlement_price.normalize():f}" + else: + price_parameter = None + + return injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket( + sender=sender, + market_id=market_id, + settlement_price=price_parameter, + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + status=status, ) + # endregion + + # region Insurance module def MsgCreateInsuranceFund( self, sender: str, @@ -941,38 +1817,53 @@ def MsgRequestRedemption( amount=self.coin(amount=amount, denom=share_denom), ) - def MsgVote( - self, - proposal_id: str, - voter: str, - option: int, - ): - return cosmos_gov_tx_pb.MsgVote(proposal_id=proposal_id, voter=voter, option=option) + # endregion - def MsgPrivilegedExecuteContract( - self, sender: str, contract: str, msg: str, **kwargs - ) -> injective_exchange_tx_pb.MsgPrivilegedExecuteContract: - return injective_exchange_tx_pb.MsgPrivilegedExecuteContract( - sender=sender, - contract_address=contract, - data=msg, - funds=kwargs.get("funds") # funds is a string of Coin strings, comma separated, - # e.g. 100000inj,20000000000usdt + # region Oracle module + def MsgRelayProviderPrices(self, sender: str, provider: str, symbols: list, prices: list): + oracle_prices = [] + + for price in prices: + scale_price = Decimal((price) * pow(10, 18)) + price_to_bytes = bytes(str(scale_price), "utf-8") + oracle_prices.append(price_to_bytes) + + return injective_oracle_tx_pb.MsgRelayProviderPrices( + sender=sender, provider=provider, symbols=symbols, prices=oracle_prices ) - def MsgInstantiateContract( - self, sender: str, admin: str, code_id: int, label: str, message: bytes, **kwargs - ) -> wasm_tx_pb.MsgInstantiateContract: - return wasm_tx_pb.MsgInstantiateContract( + def MsgRelayPriceFeedPrice(self, sender: list, base: list, quote: list, price: list): + return injective_oracle_tx_pb.MsgRelayPriceFeedPrice(sender=sender, base=base, quote=quote, price=price) + + # endregion + + # region Peggy module + def MsgSendToEth(self, denom: str, sender: str, eth_dest: str, amount: float, bridge_fee: float): + be_amount = self.create_coin_amount(amount=Decimal(str(amount)), token_name=denom) + be_bridge_fee = self.create_coin_amount(amount=Decimal(str(bridge_fee)), token_name=denom) + + return injective_peggy_tx_pb.MsgSendToEth( sender=sender, - admin=admin, - code_id=code_id, - label=label, - msg=message, - funds=kwargs.get("funds"), # funds is a list of cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin. - # The coins in the list must be sorted in alphabetical order by denoms. + eth_dest=eth_dest, + amount=be_amount, + bridge_fee=be_bridge_fee, + ) + + # endregion + + # region Staking module + def MsgDelegate(self, delegator_address: str, validator_address: str, amount: float): + be_amount = Decimal(str(amount)) * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return cosmos_staking_tx_pb.MsgDelegate( + delegator_address=delegator_address, + validator_address=validator_address, + amount=self.coin(amount=int(be_amount), denom=INJ_DENOM), ) + # endregion + + # region Tokenfactory module def msg_create_denom( self, sender: str, @@ -990,14 +1881,14 @@ def msg_create_denom( def msg_mint( self, sender: str, - amount: cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin, + amount: base_coin_pb.Coin, ) -> token_factory_tx_pb.MsgMint: return token_factory_tx_pb.MsgMint(sender=sender, amount=amount) def msg_burn( self, sender: str, - amount: cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin, + amount: base_coin_pb.Coin, ) -> token_factory_tx_pb.MsgBurn: return token_factory_tx_pb.MsgBurn(sender=sender, amount=amount) @@ -1047,14 +1938,108 @@ def msg_change_admin( new_admin=new_admin, ) - def msg_execute_contract_compat(self, sender: str, contract: str, msg: str, funds: str): - return wasmx_tx_pb.MsgExecuteContractCompat( + # endregion + + # region Wasm module + def MsgInstantiateContract( + self, sender: str, admin: str, code_id: int, label: str, message: bytes, **kwargs + ) -> wasm_tx_pb.MsgInstantiateContract: + return wasm_tx_pb.MsgInstantiateContract( + sender=sender, + admin=admin, + code_id=code_id, + label=label, + msg=message, + funds=kwargs.get("funds"), # funds is a list of base_coin_pb.Coin. + # The coins in the list must be sorted in alphabetical order by denoms. + ) + + def MsgExecuteContract(self, sender: str, contract: str, msg: str, **kwargs): + return wasm_tx_pb.MsgExecuteContract( sender=sender, contract=contract, - msg=msg, - funds=funds, + msg=bytes(msg, "utf-8"), + funds=kwargs.get("funds") # funds is a list of base_coin_pb.Coin. + # The coins in the list must be sorted in alphabetical order by denoms. + ) + + # endregion + + def MsgGrantTyped( + self, + granter: str, + grantee: str, + msg_type: str, + expire_in: int, + subaccount_id: str, + **kwargs, + ): + auth = None + if msg_type == "CreateSpotLimitOrderAuthz": + auth = injective_authz_pb.CreateSpotLimitOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CreateSpotMarketOrderAuthz": + auth = injective_authz_pb.CreateSpotMarketOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCreateSpotLimitOrdersAuthz": + auth = injective_authz_pb.BatchCreateSpotLimitOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CancelSpotOrderAuthz": + auth = injective_authz_pb.CancelSpotOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCancelSpotOrdersAuthz": + auth = injective_authz_pb.BatchCancelSpotOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CreateDerivativeLimitOrderAuthz": + auth = injective_authz_pb.CreateDerivativeLimitOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CreateDerivativeMarketOrderAuthz": + auth = injective_authz_pb.CreateDerivativeMarketOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCreateDerivativeLimitOrdersAuthz": + auth = injective_authz_pb.BatchCreateDerivativeLimitOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "CancelDerivativeOrderAuthz": + auth = injective_authz_pb.CancelDerivativeOrderAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchCancelDerivativeOrdersAuthz": + auth = injective_authz_pb.BatchCancelDerivativeOrdersAuthz( + subaccount_id=subaccount_id, market_ids=kwargs.get("market_ids") + ) + elif msg_type == "BatchUpdateOrdersAuthz": + auth = injective_authz_pb.BatchUpdateOrdersAuthz( + subaccount_id=subaccount_id, + spot_markets=kwargs.get("spot_markets"), + derivative_markets=kwargs.get("derivative_markets"), + ) + + any_auth = any_pb2.Any() + any_auth.Pack(auth, type_url_prefix="") + + grant = cosmos_authz_pb.Grant( + authorization=any_auth, + expiration=timestamp_pb2.Timestamp(seconds=(int(time()) + expire_in)), ) + return cosmos_authz_tx_pb.MsgGrant(granter=granter, grantee=grantee, grant=grant) + + def MsgVote( + self, + proposal_id: str, + voter: str, + option: int, + ): + return cosmos_gov_tx_pb.MsgVote(proposal_id=proposal_id, voter=voter, option=option) + def chain_stream_bank_balances_filter( self, accounts: Optional[List[str]] = None ) -> chain_stream_query.BankBalancesFilter: @@ -1144,7 +2129,7 @@ def MsgWithdrawValidatorCommission(self, validator_address: str): def msg_withdraw_validator_commission(self, validator_address: str): return cosmos_distribution_tx_pb.MsgWithdrawValidatorCommission(validator_address=validator_address) - def msg_fund_community_pool(self, amounts: List[cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin], depositor: str): + def msg_fund_community_pool(self, amounts: List[base_coin_pb.Coin], depositor: str): return cosmos_distribution_tx_pb.MsgFundCommunityPool(amount=amounts, depositor=depositor) def msg_update_distribution_params(self, authority: str, community_tax: str, withdraw_address_enabled: bool): @@ -1154,9 +2139,7 @@ def msg_update_distribution_params(self, authority: str, community_tax: str, wit ) return cosmos_distribution_tx_pb.MsgUpdateParams(authority=authority, params=params) - def msg_community_pool_spend( - self, authority: str, recipient: str, amount: List[cosmos_dot_base_dot_v1beta1_dot_coin__pb2.Coin] - ): + def msg_community_pool_spend(self, authority: str, recipient: str, amount: List[base_coin_pb.Coin]): return cosmos_distribution_tx_pb.MsgCommunityPoolSpend(authority=authority, recipient=recipient, amount=amount) # data field format: [request-msg-header][raw-byte-msg-response] @@ -1369,3 +2352,61 @@ def _initialize_markets_and_tokens_from_files(self): self.spot_markets = spot_markets self.derivative_markets = derivative_markets self.binary_option_markets = dict() + + def _order_mask(self, is_conditional: bool, is_buy: bool, is_market_order: bool) -> int: + order_mask = 0 + + if is_conditional: + order_mask += injective_exchange_pb.OrderMask.CONDITIONAL + else: + order_mask += injective_exchange_pb.OrderMask.REGULAR + + if is_buy: + order_mask += injective_exchange_pb.OrderMask.DIRECTION_BUY_OR_HIGHER + else: + order_mask += injective_exchange_pb.OrderMask.DIRECTION_SELL_OR_LOWER + + if is_market_order: + order_mask += injective_exchange_pb.OrderMask.TYPE_MARKET + else: + order_mask += injective_exchange_pb.OrderMask.TYPE_LIMIT + + if order_mask == 0: + order_mask = 1 + + return order_mask + + def _basic_derivative_order( + self, + market_id: str, + subaccount_id: str, + fee_recipient: str, + chain_price: Decimal, + chain_quantity: Decimal, + chain_margin: Decimal, + order_type: str, + cid: Optional[str] = None, + chain_trigger_price: Optional[Decimal] = None, + ) -> injective_exchange_pb.DerivativeOrder: + formatted_quantity = f"{chain_quantity.normalize():f}" + formatted_price = f"{chain_price.normalize():f}" + formatted_margin = f"{chain_margin.normalize():f}" + + trigger_price = chain_trigger_price or Decimal(0) + formatted_trigger_price = f"{trigger_price.normalize():f}" + + chain_order_type = injective_exchange_pb.OrderType.Value(order_type) + + return injective_exchange_pb.DerivativeOrder( + market_id=market_id, + order_info=injective_exchange_pb.OrderInfo( + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=formatted_price, + quantity=formatted_quantity, + cid=cid, + ), + order_type=chain_order_type, + margin=formatted_margin, + trigger_price=formatted_trigger_price, + ) diff --git a/pyinjective/core/market.py b/pyinjective/core/market.py index 2bd4fe1b..66063130 100644 --- a/pyinjective/core/market.py +++ b/pyinjective/core/market.py @@ -169,6 +169,17 @@ def price_to_chain_format(self, human_readable_value: Decimal, special_denom: Op return extended_chain_formatted_value + def margin_to_chain_format(self, human_readable_value: Decimal, special_denom: Optional[Denom] = None) -> Decimal: + decimals = self.quote_token.decimals if special_denom is None else special_denom.quote + min_quantity_tick_size = ( + self.min_quantity_tick_size if special_denom is None else special_denom.min_quantity_tick_size + ) + chain_formatted_value = human_readable_value * Decimal(f"1e{decimals}") + quantized_value = (chain_formatted_value // min_quantity_tick_size) * min_quantity_tick_size + extended_chain_formatted_value = quantized_value * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + return extended_chain_formatted_value + def calculate_margin_in_chain_format( self, human_readable_quantity: Decimal, diff --git a/tests/core/test_gas_limit_estimator.py b/tests/core/test_gas_limit_estimator.py index 916c47a9..293f5f25 100644 --- a/tests/core/test_gas_limit_estimator.py +++ b/tests/core/test_gas_limit_estimator.py @@ -24,26 +24,24 @@ def test_estimation_for_batch_create_spot_limit_orders(self): spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=5, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("5"), + quantity=Decimal("1"), + order_type="BUY", ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=4, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("4"), + quantity=Decimal("1"), + order_type="BUY", ), ] - message = composer.MsgBatchCreateSpotLimitOrders(sender="sender", orders=orders) + message = composer.msg_batch_create_spot_limit_orders(sender="sender", orders=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 50000 @@ -55,23 +53,23 @@ def test_estimation_for_batch_cancel_spot_orders(self): spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", ), ] - message = composer.MsgBatchCancelSpotOrders(sender="sender", data=orders) + message = composer.msg_batch_cancel_spot_orders(sender="sender", orders_data=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 50000 @@ -83,28 +81,26 @@ def test_estimation_for_batch_create_derivative_limit_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=3, - quantity=1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(3), + quantity=Decimal(1), + margin=Decimal(3), + order_type="BUY", ), - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=20, - quantity=1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(20), + quantity=Decimal(1), + margin=Decimal(20), + order_type="SELL", ), ] - message = composer.MsgBatchCreateDerivativeLimitOrders(sender="sender", orders=orders) + message = composer.msg_batch_create_derivative_limit_orders(sender="sender", orders=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 70_000 @@ -116,23 +112,23 @@ def test_estimation_for_batch_cancel_derivative_orders(self): spot_market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=spot_market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", ), ] - message = composer.MsgBatchCancelDerivativeOrders(sender="sender", data=orders) + message = composer.msg_batch_cancel_derivative_orders(sender="sender", orders_data=orders) estimator = GasLimitEstimator.for_message(message=message) expected_order_gas_limit = 60_000 @@ -144,23 +140,21 @@ def test_estimation_for_batch_update_orders_to_create_spot_orders(self): market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.SpotOrder( + composer.spot_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=5, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("5"), + quantity=Decimal("1"), + order_type="BUY", ), - composer.SpotOrder( + composer.spot_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=4, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("4"), + quantity=Decimal("1"), + order_type="BUY", ), ] message = composer.MsgBatchUpdateOrders( @@ -181,25 +175,23 @@ def test_estimation_for_batch_update_orders_to_create_derivative_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=3, - quantity=1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(3), + quantity=Decimal(1), + margin=Decimal(3), + order_type="BUY", ), - composer.DerivativeOrder( + composer.derivative_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=20, - quantity=1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(20), + quantity=Decimal(1), + margin=Decimal(20), + order_type="SELL", ), ] message = composer.MsgBatchUpdateOrders( @@ -238,25 +230,23 @@ def test_estimation_for_batch_update_orders_to_create_binary_orders(self, usdt_t ) composer.binary_option_markets[market.id] = market orders = [ - composer.BinaryOptionsOrder( + composer.binary_options_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=3, - quantity=1, - leverage=1, - is_buy=True, - is_po=False, + price=Decimal(3), + quantity=Decimal(1), + margin=Decimal(3), + order_type="BUY", ), - composer.BinaryOptionsOrder( + composer.binary_options_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=20, - quantity=1, - leverage=1, - is_buy=False, - is_reduce_only=False, + price=Decimal(20), + quantity=Decimal(1), + margin=Decimal(20), + order_type="SELL", ), ] message = composer.MsgBatchUpdateOrders( @@ -278,17 +268,17 @@ def test_estimation_for_batch_update_orders_to_cancel_spot_orders(self): market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -312,17 +302,17 @@ def test_estimation_for_batch_update_orders_to_cancel_derivative_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -346,17 +336,17 @@ def test_estimation_for_batch_update_orders_to_cancel_binary_orders(self): market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" composer = Composer(network="testnet") orders = [ - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", ), - composer.OrderData( + composer.order_data( market_id=market_id, subaccount_id="subaccount_id", order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", @@ -441,14 +431,13 @@ def test_estimation_for_exec_message(self): market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" composer = Composer(network="testnet") orders = [ - composer.SpotOrder( + composer.spot_order( market_id=market_id, subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=5, - quantity=1, - is_buy=True, - is_po=False, + price=Decimal("5"), + quantity=Decimal("1"), + order_type="BUY", ), ] inner_message = composer.MsgBatchUpdateOrders( @@ -510,15 +499,14 @@ def test_estimation_for_governance_message(self): def test_estimation_for_generic_exchange_message(self): composer = Composer(network="testnet") - message = composer.MsgCreateSpotLimitOrder( + message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) estimator = GasLimitEstimator.for_message(message=message) diff --git a/tests/core/test_market.py b/tests/core/test_market.py index ede8aea5..48c2f5e5 100644 --- a/tests/core/test_market.py +++ b/tests/core/test_market.py @@ -248,6 +248,42 @@ def test_convert_price_to_chain_format_without_fixed_denom(self, first_match_bet assert quantized_chain_format_value == chain_value + def test_convert_margin_to_chain_format_with_fixed_denom(self, first_match_bet_market: BinaryOptionMarket): + original_quantity = Decimal("123.456789") + fixed_denom = Denom( + description="Fixed denom", + base=2, + quote=4, + min_quantity_tick_size=100, + min_price_tick_size=10000, + ) + + chain_value = first_match_bet_market.margin_to_chain_format( + human_readable_value=original_quantity, + special_denom=fixed_denom, + ) + price_decimals = fixed_denom.quote + expected_value = original_quantity * Decimal(f"1e{price_decimals}") + quantized_value = (expected_value // Decimal(str(fixed_denom.min_quantity_tick_size))) * Decimal( + str(fixed_denom.min_quantity_tick_size) + ) + quantized_chain_format_value = quantized_value * Decimal("1e18") + + assert quantized_chain_format_value == chain_value + + def test_convert_margin_to_chain_format_without_fixed_denom(self, first_match_bet_market: BinaryOptionMarket): + original_quantity = Decimal("123.456789") + + chain_value = first_match_bet_market.margin_to_chain_format(human_readable_value=original_quantity) + price_decimals = first_match_bet_market.quote_token.decimals + expected_value = original_quantity * Decimal(f"1e{price_decimals}") + quantized_value = ( + expected_value // first_match_bet_market.min_quantity_tick_size + ) * first_match_bet_market.min_quantity_tick_size + quantized_chain_format_value = quantized_value * Decimal("1e18") + + assert quantized_chain_format_value == chain_value + def test_calculate_margin_for_buy_with_fixed_denom(self, first_match_bet_market: BinaryOptionMarket): original_quantity = Decimal("123.456789") original_price = Decimal("0.6789") diff --git a/tests/core/test_message_based_transaction_fee_calculator.py b/tests/core/test_message_based_transaction_fee_calculator.py index 23e263c9..b1d774e0 100644 --- a/tests/core/test_message_based_transaction_fee_calculator.py +++ b/tests/core/test_message_based_transaction_fee_calculator.py @@ -117,15 +117,14 @@ async def test_gas_fee_for_exchange_message(self): gas_price=5_000_000, ) - message = composer.MsgCreateSpotLimitOrder( + message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) transaction = Transaction() transaction.with_messages(message) @@ -148,15 +147,14 @@ async def test_gas_fee_for_msg_exec_message(self): gas_price=5_000_000, ) - inner_message = composer.MsgCreateSpotLimitOrder( + inner_message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) message = composer.MsgExec(grantee="grantee", msgs=[inner_message]) transaction = Transaction() @@ -184,15 +182,14 @@ async def test_gas_fee_for_two_messages_in_one_transaction(self): gas_price=5_000_000, ) - inner_message = composer.MsgCreateSpotLimitOrder( + inner_message = composer.msg_create_spot_limit_order( sender="sender", market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe", subaccount_id="subaccount_id", fee_recipient="fee_recipient", - price=7.523, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("7.523"), + quantity=Decimal("0.01"), + order_type="BUY", ) message = composer.MsgExec(grantee="grantee", msgs=[inner_message]) diff --git a/tests/test_composer.py b/tests/test_composer.py index a0cca2ab..2dcbd056 100644 --- a/tests/test_composer.py +++ b/tests/test_composer.py @@ -2,12 +2,11 @@ from decimal import Decimal import pytest +from google.protobuf import json_format from pyinjective.composer import Composer -from pyinjective.core.market import BinaryOptionMarket, DerivativeMarket, SpotMarket +from pyinjective.constant import ADDITIONAL_CHAIN_FORMAT_DECIMALS from pyinjective.core.network import Network -from pyinjective.proto.injective.exchange.v1beta1 import exchange_pb2 -from pyinjective.utils.denom import Denom from tests.model_fixtures.markets_fixtures import btc_usdt_perp_market # noqa: F401 from tests.model_fixtures.markets_fixtures import first_match_bet_market # noqa: F401 from tests.model_fixtures.markets_fixtures import inj_token # noqa: F401 @@ -57,211 +56,6 @@ def test_composer_initialization_from_ini_files(self): assert 6 == inj_usdt_spot_market.quote_token.decimals assert 6 == inj_usdt_perp_market.quote_token.decimals - def test_buy_spot_order_creation(self, basic_composer: Composer, inj_usdt_spot_market: SpotMarket): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - order = basic_composer.SpotOrder( - market_id=inj_usdt_spot_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - ) - - price_decimals = inj_usdt_spot_market.quote_token.decimals - inj_usdt_spot_market.base_token.decimals - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // inj_usdt_spot_market.min_price_tick_size) - * inj_usdt_spot_market.min_price_tick_size - * Decimal("1e18") - ) - chain_format_quantity = Decimal(str(quantity)) * Decimal(f"1e{inj_usdt_spot_market.base_token.decimals}") - expected_quantity = ( - (chain_format_quantity // inj_usdt_spot_market.min_quantity_tick_size) - * inj_usdt_spot_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert order.market_id == inj_usdt_spot_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.trigger_price == "0" - - def test_buy_derivative_order_creation(self, basic_composer: Composer, btc_usdt_perp_market: DerivativeMarket): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - leverage = 2 - order = basic_composer.DerivativeOrder( - market_id=btc_usdt_perp_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - leverage=leverage, - ) - - price_decimals = btc_usdt_perp_market.quote_token.decimals - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // btc_usdt_perp_market.min_price_tick_size) - * btc_usdt_perp_market.min_price_tick_size - * Decimal("1e18") - ) - chain_format_quantity = Decimal(str(quantity)) - expected_quantity = ( - (chain_format_quantity // btc_usdt_perp_market.min_quantity_tick_size) - * btc_usdt_perp_market.min_quantity_tick_size - * Decimal("1e18") - ) - chain_format_margin = (chain_format_quantity * chain_format_price) / Decimal(leverage) - expected_margin = ( - (chain_format_margin // btc_usdt_perp_market.min_quantity_tick_size) - * btc_usdt_perp_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert order.market_id == btc_usdt_perp_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.margin == str(int(expected_margin)) - assert order.trigger_price == "0" - - def test_increase_position_margin(self, basic_composer: Composer, btc_usdt_perp_market: DerivativeMarket): - sender = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - amount = 1587.789 - message = basic_composer.MsgIncreasePositionMargin( - sender=sender, - source_subaccount_id="1", - destination_subaccount_id="2", - market_id=btc_usdt_perp_market.id, - amount=amount, - ) - - price_decimals = btc_usdt_perp_market.quote_token.decimals - chain_format_margin = Decimal(str(amount)) * Decimal(f"1e{price_decimals}") - expected_margin = ( - (chain_format_margin // btc_usdt_perp_market.min_quantity_tick_size) - * btc_usdt_perp_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert message.market_id == btc_usdt_perp_market.id - assert message.sender == sender - assert message.source_subaccount_id == "1" - assert message.destination_subaccount_id == "2" - assert message.amount == str(int(expected_margin)) - - def test_buy_binary_option_order_creation_with_fixed_denom( - self, basic_composer: Composer, first_match_bet_market: BinaryOptionMarket - ): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - fixed_denom = Denom( - description="Fixed denom", - base=2, - quote=6, - min_price_tick_size=1000, - min_quantity_tick_size=10000, - ) - - order = basic_composer.BinaryOptionsOrder( - market_id=first_match_bet_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - denom=fixed_denom, - ) - - price_decimals = fixed_denom.quote - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // Decimal(str(fixed_denom.min_price_tick_size))) - * Decimal(str(fixed_denom.min_price_tick_size)) - * Decimal("1e18") - ) - quantity_decimals = fixed_denom.base - chain_format_quantity = Decimal(str(quantity)) * Decimal(f"1e{quantity_decimals}") - expected_quantity = ( - (chain_format_quantity // Decimal(str(fixed_denom.min_quantity_tick_size))) - * Decimal(str(fixed_denom.min_quantity_tick_size)) - * Decimal("1e18") - ) - chain_format_margin = chain_format_quantity * chain_format_price - expected_margin = ( - (chain_format_margin // Decimal(str(fixed_denom.min_quantity_tick_size))) - * Decimal(str(fixed_denom.min_quantity_tick_size)) - * Decimal("1e18") - ) - - assert order.market_id == first_match_bet_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.margin == str(int(expected_margin)) - assert order.trigger_price == "0" - - def test_buy_binary_option_order_creation_without_fixed_denom( - self, - basic_composer: Composer, - first_match_bet_market: BinaryOptionMarket, - ): - fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" - price = 6.869 - quantity = 1587 - - order = basic_composer.BinaryOptionsOrder( - market_id=first_match_bet_market.id, - subaccount_id="1", - fee_recipient=fee_recipient, - price=price, - quantity=quantity, - is_buy=True, - ) - - price_decimals = first_match_bet_market.quote_token.decimals - chain_format_price = Decimal(str(price)) * Decimal(f"1e{price_decimals}") - expected_price = ( - (chain_format_price // first_match_bet_market.min_price_tick_size) - * first_match_bet_market.min_price_tick_size - * Decimal("1e18") - ) - chain_format_quantity = Decimal(str(quantity)) - expected_quantity = ( - (chain_format_quantity // first_match_bet_market.min_quantity_tick_size) - * first_match_bet_market.min_quantity_tick_size - * Decimal("1e18") - ) - chain_format_margin = chain_format_quantity * chain_format_price - expected_margin = ( - (chain_format_margin // first_match_bet_market.min_quantity_tick_size) - * first_match_bet_market.min_quantity_tick_size - * Decimal("1e18") - ) - - assert order.market_id == first_match_bet_market.id - assert order.order_info.subaccount_id == "1" - assert order.order_info.fee_recipient == fee_recipient - assert order.order_info.price == str(int(expected_price)) - assert order.order_info.quantity == str(int(expected_quantity)) - assert order.order_type == exchange_pb2.OrderType.BUY - assert order.margin == str(int(expected_margin)) - assert order.trigger_price == "0" - def test_msg_create_denom(self, basic_composer: Composer): sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" subdenom = "inj-test" @@ -380,3 +174,1259 @@ def test_msg_execute_contract_compat(self, basic_composer): assert message.contract == contract assert message.msg == msg assert message.funds == funds + + def test_msg_deposit(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=Decimal(amount)) + + message = basic_composer.msg_deposit( + sender=sender, + subaccount_id=subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_withdraw(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=Decimal(amount)) + + message = basic_composer.msg_withdraw( + sender=sender, + subaccount_id=subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_spot_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "INJ/USDT" + base_denom = "INJ" + quote_denom = "USDT" + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + + base_token = basic_composer.tokens[base_denom] + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals - base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal( + f"1e{base_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + + message = basic_composer.msg_instant_spot_market_launch( + sender=sender, + ticker=ticker, + base_denom=base_denom, + quote_denom=quote_denom, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "baseDenom": base_token.denom, + "quoteDenom": quote_token.denom, + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_perpetual_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "BTC/INJ PERP" + quote_denom = "INJ" + oracle_base = "BTC" + oracle_quote = "INJ" + oracle_scale_factor = 6 + oracle_type = "Band" + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + maker_fee_rate = Decimal("0.001") + taker_fee_rate = Decimal("-0.002") + initial_margin_ratio = Decimal("0.05") + maintenance_margin_ratio = Decimal("0.03") + + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + message = basic_composer.msg_instant_perpetual_market_launch( + sender=sender, + ticker=ticker, + quote_denom=quote_denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=oracle_type, + maker_fee_rate=maker_fee_rate, + taker_fee_rate=taker_fee_rate, + initial_margin_ratio=initial_margin_ratio, + maintenance_margin_ratio=maintenance_margin_ratio, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "quoteDenom": quote_token.denom, + "oracleBase": oracle_base, + "oracleQuote": oracle_quote, + "oracleScaleFactor": oracle_scale_factor, + "oracleType": oracle_type, + "makerFeeRate": f"{expected_maker_fee_rate.normalize():f}", + "takerFeeRate": f"{expected_taker_fee_rate.normalize():f}", + "initialMarginRatio": f"{expected_initial_margin_ratio.normalize():f}", + "maintenanceMarginRatio": f"{expected_maintenance_margin_ratio.normalize():f}", + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_expiry_futures_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "BTC/INJ PERP" + quote_denom = "INJ" + oracle_base = "BTC" + oracle_quote = "INJ" + oracle_scale_factor = 6 + oracle_type = "Band" + expiry = 1630000000 + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + maker_fee_rate = Decimal("0.001") + taker_fee_rate = Decimal("-0.002") + initial_margin_ratio = Decimal("0.05") + maintenance_margin_ratio = Decimal("0.03") + + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_initial_margin_ratio = initial_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maintenance_margin_ratio = maintenance_margin_ratio * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + message = basic_composer.msg_instant_expiry_futures_market_launch( + sender=sender, + ticker=ticker, + quote_denom=quote_denom, + oracle_base=oracle_base, + oracle_quote=oracle_quote, + oracle_scale_factor=oracle_scale_factor, + oracle_type=oracle_type, + expiry=expiry, + maker_fee_rate=maker_fee_rate, + taker_fee_rate=taker_fee_rate, + initial_margin_ratio=initial_margin_ratio, + maintenance_margin_ratio=maintenance_margin_ratio, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "quoteDenom": quote_token.denom, + "oracleBase": oracle_base, + "oracleQuote": oracle_quote, + "oracleType": oracle_type, + "oracleScaleFactor": oracle_scale_factor, + "expiry": str(expiry), + "makerFeeRate": f"{expected_maker_fee_rate.normalize():f}", + "takerFeeRate": f"{expected_taker_fee_rate.normalize():f}", + "initialMarginRatio": f"{expected_initial_margin_ratio.normalize():f}", + "maintenanceMarginRatio": f"{expected_maintenance_margin_ratio.normalize():f}", + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_spot_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.spot_order( + market_id=spot_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = spot_market.price_to_chain_format(human_readable_value=price) + expected_quantity = spot_market.quantity_to_chain_format(human_readable_value=quantity) + expected_trigger_price = spot_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_order = { + "marketId": spot_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=order, + including_default_value_fields=True, + ) + assert dict_message == expected_order + + def test_derivative_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.derivative_order( + market_id=derivative_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = derivative_market.price_to_chain_format(human_readable_value=price) + expected_quantity = derivative_market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = derivative_market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = derivative_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_order = { + "marketId": derivative_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "margin": f"{expected_margin.normalize():f}", + "triggerPrice": f"{expected_trigger_price.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=order, + including_default_value_fields=True, + ) + assert dict_message == expected_order + + def test_msg_create_spot_limit_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_spot_limit_order( + market_id=spot_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = spot_market.price_to_chain_format(human_readable_value=price) + expected_quantity = spot_market.quantity_to_chain_format(human_readable_value=quantity) + expected_trigger_price = spot_market.price_to_chain_format(human_readable_value=trigger_price) + + assert "injective.exchange.v1beta1.MsgCreateSpotLimitOrder" == message.DESCRIPTOR.full_name + expected_message = { + "sender": sender, + "order": { + "marketId": spot_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_create_spot_limit_orders(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.spot_order( + market_id=spot_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + message = basic_composer.msg_batch_create_spot_limit_orders( + sender=sender, + orders=[order], + ) + + expected_message = { + "sender": sender, + "orders": [json_format.MessageToDict(message=order, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_spot_market_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_spot_market_order( + market_id=spot_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = spot_market.price_to_chain_format(human_readable_value=price) + expected_quantity = spot_market.quantity_to_chain_format(human_readable_value=quantity) + expected_trigger_price = spot_market.price_to_chain_format(human_readable_value=trigger_price) + + assert "injective.exchange.v1beta1.MsgCreateSpotMarketOrder" == message.DESCRIPTOR.full_name + expected_message = { + "sender": sender, + "order": { + "marketId": spot_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_cancel_spot_order(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + order_hash = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + cid = "test_cid" + + message = basic_composer.msg_cancel_spot_order( + market_id=spot_market.id, + sender=sender, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + ) + + expected_message = { + "sender": sender, + "marketId": spot_market.id, + "subaccountId": subaccount_id, + "orderHash": order_hash, + "cid": cid, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_cancel_spot_orders(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + + order_data = basic_composer.order_data( + market_id=spot_market.id, + subaccount_id=subaccount_id, + order_hash="0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000", + ) + + message = basic_composer.msg_batch_cancel_spot_orders( + sender=sender, + orders_data=[order_data], + ) + + assert "injective.exchange.v1beta1.MsgBatchCancelSpotOrders" == message.DESCRIPTOR.full_name + expected_message = { + "sender": sender, + "data": [json_format.MessageToDict(message=order_data, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_update_orders(self, basic_composer): + spot_market = list(basic_composer.spot_markets.values())[0] + derivative_market = list(basic_composer.derivative_markets.values())[0] + binary_options_market = list(basic_composer.binary_option_markets.values())[0] + + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + spot_market_id = spot_market.id + derivative_market_id = derivative_market.id + binary_options_market_id = binary_options_market.id + spot_order_to_cancel = basic_composer.order_data( + market_id=spot_market_id, + subaccount_id=subaccount_id, + order_hash="0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000", + ) + derivative_order_to_cancel = basic_composer.order_data( + market_id=derivative_market_id, + subaccount_id=subaccount_id, + order_hash="0x222daa22f60fe9f075ed0ca583459e121c23e64431c3fbffdedda04598ede0d2", + ) + binary_options_order_to_cancel = basic_composer.order_data( + market_id=binary_options_market_id, + subaccount_id=subaccount_id, + order_hash="0x7ee76255d7ca763c56b0eab9828fca89fdd3739645501c8a80f58b62b4f76da5", + ) + spot_order_to_create = basic_composer.spot_order( + market_id=spot_market_id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + order_type="BUY", + cid="test_cid", + trigger_price=Decimal("43.5"), + ) + derivative_order_to_create = basic_composer.derivative_order( + market_id=derivative_market_id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + margin=Decimal("36.1") * Decimal("100"), + order_type="BUY", + ) + binary_options_order_to_create = basic_composer.binary_options_order( + market_id=binary_options_market_id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + margin=Decimal("36.1") * Decimal("100"), + order_type="BUY", + ) + + message = basic_composer.msg_batch_update_orders( + sender=sender, + subaccount_id=subaccount_id, + spot_market_ids_to_cancel_all=[spot_market_id], + derivative_market_ids_to_cancel_all=[derivative_market_id], + spot_orders_to_cancel=[spot_order_to_cancel], + derivative_orders_to_cancel=[derivative_order_to_cancel], + spot_orders_to_create=[spot_order_to_create], + derivative_orders_to_create=[derivative_order_to_create], + binary_options_orders_to_cancel=[binary_options_order_to_cancel], + binary_options_market_ids_to_cancel_all=[binary_options_market_id], + binary_options_orders_to_create=[binary_options_order_to_create], + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "spotMarketIdsToCancelAll": [spot_market_id], + "derivativeMarketIdsToCancelAll": [derivative_market_id], + "spotOrdersToCancel": [ + json_format.MessageToDict(message=spot_order_to_cancel, including_default_value_fields=True) + ], + "derivativeOrdersToCancel": [ + json_format.MessageToDict(message=derivative_order_to_cancel, including_default_value_fields=True) + ], + "spotOrdersToCreate": [ + json_format.MessageToDict(message=spot_order_to_create, including_default_value_fields=True) + ], + "derivativeOrdersToCreate": [ + json_format.MessageToDict(message=derivative_order_to_create, including_default_value_fields=True) + ], + "binaryOptionsOrdersToCancel": [ + json_format.MessageToDict(message=binary_options_order_to_cancel, including_default_value_fields=True) + ], + "binaryOptionsMarketIdsToCancelAll": [binary_options_market_id], + "binaryOptionsOrdersToCreate": [ + json_format.MessageToDict(message=binary_options_order_to_create, including_default_value_fields=True) + ], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_privileged_execute_contract(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + contract_address = "inj1ady3s7whq30l4fx8sj3x6muv5mx4dfdlcpv8n7" + data = "test_data" + funds = "100inj,420peggy0x44C21afAaF20c270EBbF5914Cfc3b5022173FEB7" + + message = basic_composer.msg_privileged_execute_contract( + sender=sender, + contract_address=contract_address, + data=data, + funds=funds, + ) + + expected_message = { + "sender": sender, + "funds": funds, + "contractAddress": contract_address, + "data": data, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_derivative_limit_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_derivative_limit_order( + market_id=derivative_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = derivative_market.price_to_chain_format(human_readable_value=price) + expected_quantity = derivative_market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = derivative_market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = derivative_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": derivative_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_create_derivative_limit_orders(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + order = basic_composer.derivative_order( + market_id=derivative_market.id, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=price * quantity, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + message = basic_composer.msg_batch_create_derivative_limit_orders( + sender=sender, + orders=[order], + ) + + expected_message = { + "sender": sender, + "orders": [json_format.MessageToDict(message=order, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_derivative_market_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_derivative_market_order( + market_id=derivative_market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = derivative_market.price_to_chain_format(human_readable_value=price) + expected_quantity = derivative_market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = derivative_market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = derivative_market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": derivative_market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_cancel_derivative_order(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + order_hash = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + cid = "test_cid" + is_conditional = False + is_buy = True + is_market_order = False + + expected_order_mask = basic_composer._order_mask( + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + message = basic_composer.msg_cancel_derivative_order( + market_id=derivative_market.id, + sender=sender, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + expected_message = { + "sender": sender, + "marketId": derivative_market.id, + "subaccountId": subaccount_id, + "orderHash": order_hash, + "orderMask": expected_order_mask, + "cid": cid, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_batch_cancel_derivative_orders(self, basic_composer): + derivative_market = list(basic_composer.derivative_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + + order_data = basic_composer.order_data( + market_id=derivative_market.id, + subaccount_id=subaccount_id, + order_hash="0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000", + ) + + message = basic_composer.msg_batch_cancel_derivative_orders( + sender=sender, + orders_data=[order_data], + ) + + expected_message = { + "sender": sender, + "data": [json_format.MessageToDict(message=order_data, including_default_value_fields=True)], + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_instant_binary_options_market_launch(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + ticker = "B2500/INJ" + oracle_symbol = "B2500_1/INJ" + oracle_provider = "Injective" + oracle_scale_factor = 6 + oracle_type = "Band" + quote_denom = "INJ" + min_price_tick_size = Decimal("0.01") + min_quantity_tick_size = Decimal("1") + maker_fee_rate = Decimal("0.001") + taker_fee_rate = Decimal("-0.002") + expiration_timestamp = 1630000000 + settlement_timestamp = 1660000000 + admin = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + + quote_token = basic_composer.tokens[quote_denom] + + expected_min_price_tick_size = min_price_tick_size * Decimal( + f"1e{quote_token.decimals + ADDITIONAL_CHAIN_FORMAT_DECIMALS}" + ) + expected_min_quantity_tick_size = min_quantity_tick_size * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_maker_fee_rate = maker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + expected_taker_fee_rate = taker_fee_rate * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}") + + message = basic_composer.msg_instant_binary_options_market_launch( + sender=sender, + ticker=ticker, + oracle_symbol=oracle_symbol, + oracle_provider=oracle_provider, + oracle_type=oracle_type, + oracle_scale_factor=oracle_scale_factor, + maker_fee_rate=maker_fee_rate, + taker_fee_rate=taker_fee_rate, + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + admin=admin, + quote_denom=quote_denom, + min_price_tick_size=min_price_tick_size, + min_quantity_tick_size=min_quantity_tick_size, + ) + + expected_message = { + "sender": sender, + "ticker": ticker, + "oracleSymbol": oracle_symbol, + "oracleProvider": oracle_provider, + "oracleType": oracle_type, + "oracleScaleFactor": oracle_scale_factor, + "makerFeeRate": f"{expected_maker_fee_rate.normalize():f}", + "takerFeeRate": f"{expected_taker_fee_rate.normalize():f}", + "expirationTimestamp": str(expiration_timestamp), + "settlementTimestamp": str(settlement_timestamp), + "admin": admin, + "quoteDenom": quote_token.denom, + "minPriceTickSize": f"{expected_min_price_tick_size.normalize():f}", + "minQuantityTickSize": f"{expected_min_quantity_tick_size.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_binary_options_limit_order(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_binary_options_limit_order( + market_id=market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = market.price_to_chain_format(human_readable_value=price) + expected_quantity = market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_create_binary_options_market_order(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + price = Decimal("36.1") + quantity = Decimal("100") + margin = price * quantity + order_type = "BUY" + cid = "test_cid" + trigger_price = Decimal("43.5") + + message = basic_composer.msg_create_binary_options_market_order( + market_id=market.id, + sender=sender, + subaccount_id=subaccount_id, + fee_recipient=fee_recipient, + price=price, + quantity=quantity, + margin=margin, + order_type=order_type, + cid=cid, + trigger_price=trigger_price, + ) + + expected_price = market.price_to_chain_format(human_readable_value=price) + expected_quantity = market.quantity_to_chain_format(human_readable_value=quantity) + expected_margin = market.margin_to_chain_format(human_readable_value=margin) + expected_trigger_price = market.price_to_chain_format(human_readable_value=trigger_price) + + expected_message = { + "sender": sender, + "order": { + "marketId": market.id, + "orderInfo": { + "subaccountId": subaccount_id, + "feeRecipient": fee_recipient, + "price": f"{expected_price.normalize():f}", + "quantity": f"{expected_quantity.normalize():f}", + "cid": cid, + }, + "margin": f"{expected_margin.normalize():f}", + "orderType": order_type, + "triggerPrice": f"{expected_trigger_price.normalize():f}", + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_cancel_derivative_order(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + order_hash = "0x5e249f0e8cb406f41de16e1bd6f6b55e7bc75add000000000000000000000000" + cid = "test_cid" + is_conditional = False + is_buy = True + is_market_order = False + + expected_order_mask = basic_composer._order_mask( + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + message = basic_composer.msg_cancel_derivative_order( + market_id=market.id, + sender=sender, + subaccount_id=subaccount_id, + order_hash=order_hash, + cid=cid, + is_conditional=is_conditional, + is_buy=is_buy, + is_market_order=is_market_order, + ) + + expected_message = { + "sender": sender, + "marketId": market.id, + "subaccountId": subaccount_id, + "orderHash": order_hash, + "orderMask": expected_order_mask, + "cid": cid, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_subaccount_transfer(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + source_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + destination_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000002" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=amount) + + message = basic_composer.msg_subaccount_transfer( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "sourceSubaccountId": source_subaccount_id, + "destinationSubaccountId": destination_subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_external_transfer(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + source_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + destination_subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000" + amount = Decimal(100) + denom = "INJ" + + token = basic_composer.tokens[denom] + + expected_amount = token.chain_formatted_value(human_readable_value=amount) + + message = basic_composer.msg_subaccount_transfer( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + amount=amount, + denom=denom, + ) + + expected_message = { + "sender": sender, + "sourceSubaccountId": source_subaccount_id, + "destinationSubaccountId": destination_subaccount_id, + "amount": { + "amount": f"{expected_amount.normalize():f}", + "denom": token.denom, + }, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_liquidate_position(self, basic_composer): + market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + order = basic_composer.derivative_order( + market_id=market.id, + subaccount_id=subaccount_id, + fee_recipient="inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r", + price=Decimal("36.1"), + quantity=Decimal("100"), + margin=Decimal("36.1") * Decimal("100"), + order_type="BUY", + ) + + message = basic_composer.msg_liquidate_position( + sender=sender, + subaccount_id=subaccount_id, + market_id=market.id, + order=order, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "marketId": market.id, + "order": json_format.MessageToDict(message=order, including_default_value_fields=True), + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_emergency_settle_market(self, basic_composer): + market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + + message = basic_composer.msg_emergency_settle_market( + sender=sender, + subaccount_id=subaccount_id, + market_id=market.id, + ) + + expected_message = { + "sender": sender, + "subaccountId": subaccount_id, + "marketId": market.id, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_external_transfer(self, basic_composer): + market = list(basic_composer.derivative_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + source_subaccount_id = "0x893f2abf8034627e50cbc63923120b1122503ce0000000000000000000000001" + destination_subaccount_id = "0xc6fe5d33615a1c52c08018c47e8bc53646a0e101000000000000000000000000" + amount = Decimal(100) + + expected_amount = market.margin_to_chain_format(human_readable_value=amount) + + message = basic_composer.msg_increase_position_margin( + sender=sender, + source_subaccount_id=source_subaccount_id, + destination_subaccount_id=destination_subaccount_id, + market_id=market.id, + amount=amount, + ) + + expected_message = { + "sender": sender, + "sourceSubaccountId": source_subaccount_id, + "destinationSubaccountId": destination_subaccount_id, + "marketId": market.id, + "amount": f"{expected_amount.normalize():f}", + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_rewards_opt_out(self, basic_composer): + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + + message = basic_composer.msg_rewards_opt_out( + sender=sender, + ) + + expected_message = { + "sender": sender, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message + + def test_msg_admin_update_binary_options_market(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + sender = "inj1apmvarl2xyv6kecx2ukkeymddw3we4zkygjyc0" + status = "Paused" + settlement_price = Decimal("100.5") + expiration_timestamp = 1630000000 + settlement_timestamp = 1660000000 + + expected_settlement_price = market.price_to_chain_format(human_readable_value=settlement_price) + + message = basic_composer.msg_admin_update_binary_options_market( + sender=sender, + market_id=market.id, + status=status, + settlement_price=settlement_price, + expiration_timestamp=expiration_timestamp, + settlement_timestamp=settlement_timestamp, + ) + + expected_message = { + "sender": sender, + "marketId": market.id, + "settlementPrice": f"{expected_settlement_price.normalize():f}", + "expirationTimestamp": str(expiration_timestamp), + "settlementTimestamp": str(settlement_timestamp), + "status": status, + } + dict_message = json_format.MessageToDict( + message=message, + including_default_value_fields=True, + ) + assert dict_message == expected_message diff --git a/tests/test_composer_deprecation_warnings.py b/tests/test_composer_deprecation_warnings.py new file mode 100644 index 00000000..20a86779 --- /dev/null +++ b/tests/test_composer_deprecation_warnings.py @@ -0,0 +1,522 @@ +import warnings +from decimal import Decimal + +import pytest + +from pyinjective.composer import Composer +from pyinjective.core.network import Network +from tests.model_fixtures.markets_fixtures import btc_usdt_perp_market # noqa: F401 +from tests.model_fixtures.markets_fixtures import first_match_bet_market # noqa: F401 +from tests.model_fixtures.markets_fixtures import inj_token # noqa: F401 +from tests.model_fixtures.markets_fixtures import inj_usdt_spot_market # noqa: F401 +from tests.model_fixtures.markets_fixtures import usdt_perp_token # noqa: F401 +from tests.model_fixtures.markets_fixtures import usdt_token # noqa: F401 + + +class TestComposerDeprecationWarnings: + @pytest.fixture + def basic_composer(self, inj_usdt_spot_market, btc_usdt_perp_market, first_match_bet_market): + composer = Composer( + network=Network.devnet().string(), + spot_markets={inj_usdt_spot_market.id: inj_usdt_spot_market}, + derivative_markets={btc_usdt_perp_market.id: btc_usdt_perp_market}, + binary_option_markets={first_match_bet_market.id: first_match_bet_market}, + tokens={ + inj_usdt_spot_market.base_token.symbol: inj_usdt_spot_market.base_token, + inj_usdt_spot_market.quote_token.symbol: inj_usdt_spot_market.quote_token, + btc_usdt_perp_market.quote_token.symbol: btc_usdt_perp_market.quote_token, + }, + ) + + return composer + + def test_msg_deposit_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgDeposit(sender="sender", subaccount_id="subaccount id", amount=1, denom="INJ") + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_deposit instead" + + def test_msg_withdraw_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgWithdraw(sender="sender", subaccount_id="subaccount id", amount=1, denom="USDT") + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_withdraw instead" + + def teste_order_data_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.OrderData( + market_id="market id", + subaccount_id="subaccount id", + order_hash="order hash", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use order_data instead" + + def test_spot_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.SpotOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + is_buy=True, + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use spot_order instead" + + def test_derivative_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.DerivativeOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + is_buy=True, + cid="cid", + leverage=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use derivative_order instead" + + def test_msg_create_spot_limit_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateSpotLimitOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_create_spot_limit_order instead" + ) + + def test_msg_batch_create_spot_limit_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + order = composer.spot_order( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=Decimal(1), + quantity=Decimal(1), + order_type="BUY", + ) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCreateSpotLimitOrders( + sender="sender", + orders=[order], + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_create_spot_limit_orders instead" + ) + + def test_msg_create_spot_market_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateSpotMarketOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + is_buy=True, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_spot_market_order instead" + ) + + def test_msg_cancel_spot_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCancelSpotOrder( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + sender="sender", + subaccount_id="subaccount id", + order_hash="order hash", + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_cancel_spot_order instead" + + def test_msg_batch_cancel_spot_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + orders = [ + composer.order_data( + market_id="0xa508cb32923323679f29a032c70342c147c17d0145625922b0ef22e955c844c0", + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", + ), + ] + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCancelSpotOrders(sender="sender", data=orders) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_cancel_spot_orders instead" + ) + + def test_msg_batch_update_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchUpdateOrders(sender="sender") + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_batch_update_orders instead" + + def test_msg_privileged_execute_contract_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgPrivilegedExecuteContract( + sender="sender", + contract="contract", + msg="msg", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_privileged_execute_contract instead" + ) + + def test_msg_create_derivative_limit_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateDerivativeLimitOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + leverage=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_derivative_limit_order instead" + ) + + def test_msg_batch_create_derivative_limit_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + order = composer.derivative_order( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=Decimal(1), + quantity=Decimal(1), + margin=Decimal(1), + order_type="BUY", + ) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCreateDerivativeLimitOrders( + sender="sender", + orders=[order], + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_create_derivative_limit_orders instead" + ) + + def test_msg_create_derivative_market_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCreateDerivativeMarketOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + leverage=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_derivative_market_order instead" + ) + + def test_msg_cancel_derivative_order_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgCancelDerivativeOrder( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + sender="sender", + subaccount_id="subaccount id", + order_hash="order hash", + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_cancel_derivative_order instead" + ) + + def test_msg_batch_cancel_derivative_orders_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + orders = [ + composer.order_data( + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + subaccount_id="subaccount_id", + order_hash="0x3870fbdd91f07d54425147b1bb96404f4f043ba6335b422a6d494d285b387f2d", + ), + ] + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgBatchCancelDerivativeOrders(sender="sender", data=orders) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_batch_cancel_derivative_orders instead" + ) + + def test_msg_instant_binary_options_market_launch_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgInstantBinaryOptionsMarketLaunch( + sender="sender", + ticker="B2400/INJ", + oracle_symbol="B2400/INJ", + oracle_provider="injective", + oracle_type="Band", + oracle_scale_factor=6, + maker_fee_rate=0.001, + taker_fee_rate=0.001, + expiration_timestamp=1630000000, + settlement_timestamp=1630000000, + quote_denom="inj", + quote_decimals=18, + min_price_tick_size=0.01, + min_quantity_tick_size=0.01, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_instant_binary_options_market_launch instead" + ) + + def test_msg_create_binary_options_limit_order_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgCreateBinaryOptionsLimitOrder( + market_id=market.id, + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + is_buy=True, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_binary_options_limit_order instead" + ) + + def test_msg_create_binary_options_market_order_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgCreateBinaryOptionsMarketOrder( + market_id=market.id, + sender="sender", + subaccount_id="subaccount id", + fee_recipient="fee recipient", + price=1, + quantity=1, + cid="cid", + is_buy=True, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_create_binary_options_market_order instead" + ) + + def test_msg_cancel_binary_options_order_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgCancelBinaryOptionsOrder( + market_id=market.id, + sender="sender", + subaccount_id="subaccount id", + order_hash="order hash", + cid="cid", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_cancel_binary_options_order instead" + ) + + def test_msg_subaccount_transfer_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgSubaccountTransfer( + sender="sender", + source_subaccount_id="source subaccount id", + destination_subaccount_id="destination subaccount id", + amount=1, + denom="INJ", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_subaccount_transfer instead" + + def test_msg_external_transfer_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgExternalTransfer( + sender="sender", + source_subaccount_id="source subaccount id", + destination_subaccount_id="destination subaccount id", + amount=1, + denom="INJ", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_external_transfer instead" + + def test_msg_liquidate_position_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgLiquidatePosition( + sender="sender", + subaccount_id="subaccount id", + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_liquidate_position instead" + + def test_msg_increase_position_margin_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgIncreasePositionMargin( + sender="sender", + source_subaccount_id="source_subaccount id", + destination_subaccount_id="destination_subaccount id", + market_id="0x7cc8b10d7deb61e744ef83bdec2bbcf4a056867e89b062c6a453020ca82bd4e4", + amount=1, + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_increase_position_margin instead" + ) + + def test_msg_rewards_opt_out_deprecation_warning(self): + composer = Composer(network=Network.devnet().string()) + + with warnings.catch_warnings(record=True) as all_warnings: + composer.MsgRewardsOptOut( + sender="sender", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert str(deprecation_warnings[0].message) == "This method is deprecated. Use msg_rewards_opt_out instead" + + def test_msg_admin_update_binary_options_market_deprecation_warning(self, basic_composer): + market = list(basic_composer.binary_option_markets.values())[0] + + with warnings.catch_warnings(record=True) as all_warnings: + basic_composer.MsgAdminUpdateBinaryOptionsMarket( + sender="sender", + market_id=market.id, + status="Paused", + ) + + deprecation_warnings = [warning for warning in all_warnings if issubclass(warning.category, DeprecationWarning)] + assert len(deprecation_warnings) == 1 + assert ( + str(deprecation_warnings[0].message) + == "This method is deprecated. Use msg_admin_update_binary_options_market instead" + ) diff --git a/tests/test_orderhash.py b/tests/test_orderhash.py index c57b6305..c2940d8d 100644 --- a/tests/test_orderhash.py +++ b/tests/test_orderhash.py @@ -1,3 +1,5 @@ +from decimal import Decimal + from pyinjective import PrivateKey from pyinjective.composer import Composer from pyinjective.core.network import Network @@ -22,23 +24,21 @@ def test_spot_order_hash(self, requests_mock): fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" spot_orders = [ - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=0.524, - quantity=0.01, - is_buy=True, - is_po=False, + price=Decimal("0.524"), + quantity=Decimal("0.01"), + order_type="BUY", ), - composer.SpotOrder( + composer.spot_order( market_id=spot_market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, - price=27.92, - quantity=0.01, - is_buy=False, - is_po=False, + price=Decimal("27.92"), + quantity=Decimal("0.01"), + order_type="SELL", ), ] From 189354a78cbad2d71df7466460516e96d3fcb610 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 27 Feb 2024 10:50:54 -0300 Subject: [PATCH 37/44] (feat) Adde CodeRabbit configuration file --- .coderabbit.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .coderabbit.yaml diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 00000000..8e534ba3 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,6 @@ +reviews: + auto_review: + base_branches: + - "master" + - "dev" + - "feat/.*" From 4dfde9a6568fa5955cf732c455ef5a6d4b5b7f80 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 20 Feb 2024 12:52:10 -0300 Subject: [PATCH 38/44] (feat) Added support for all chain exchange module queries. Included new example scripts for all the queries and unit tests. --- .../{17_MsgSubaccountTransfer.py => 10_MsgSubaccountTransfer.py} | 0 .../{9_MsgBatchUpdateOrders.py => 11_MsgBatchUpdateOrders.py} | 0 .../exchange/{21_MsgRewardsOptOut.py => 12_MsgRewardsOptOut.py} | 0 .../{18_MsgExternalTransfer.py => 15_ExternalTransfer.py} | 0 ...ptionsLimitOrder.py => 16_MsgCreateBinaryOptionsLimitOrder.py} | 0 ...ionsMarketOrder.py => 17_MsgCreateBinaryOptionsMarketOrder.py} | 0 ...celBinaryOptionsOrder.py => 18_MsgCancelBinaryOptionsOrder.py} | 0 ...{6_MsgCreateSpotLimitOrder.py => 3_MsgCreateSpotLimitOrder.py} | 0 ..._MsgCreateSpotMarketOrder.py => 4_MsgCreateSpotMarketOrder.py} | 0 .../exchange/{8_MsgCancelSpotOrder.py => 5_MsgCancelSpotOrder.py} | 0 ...erivativeMarketOrder.py => 6_MsgCreateDerivativeLimitOrder.py} | 0 ...erivativeLimitOrder.py => 7_MsgCreateDerivativeMarketOrder.py} | 0 ..._MsgCancelDerivativeOrder.py => 8_MsgCancelDerivativeOrder.py} | 0 .../chain_client/exchange/{2_MsgWithdraw.py => 9_MsgWithdraw.py} | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename examples/chain_client/exchange/{17_MsgSubaccountTransfer.py => 10_MsgSubaccountTransfer.py} (100%) rename examples/chain_client/exchange/{9_MsgBatchUpdateOrders.py => 11_MsgBatchUpdateOrders.py} (100%) rename examples/chain_client/exchange/{21_MsgRewardsOptOut.py => 12_MsgRewardsOptOut.py} (100%) rename examples/chain_client/exchange/{18_MsgExternalTransfer.py => 15_ExternalTransfer.py} (100%) rename examples/chain_client/exchange/{14_MsgCreateBinaryOptionsLimitOrder.py => 16_MsgCreateBinaryOptionsLimitOrder.py} (100%) rename examples/chain_client/exchange/{15_MsgCreateBinaryOptionsMarketOrder.py => 17_MsgCreateBinaryOptionsMarketOrder.py} (100%) rename examples/chain_client/exchange/{16_MsgCancelBinaryOptionsOrder.py => 18_MsgCancelBinaryOptionsOrder.py} (100%) rename examples/chain_client/exchange/{6_MsgCreateSpotLimitOrder.py => 3_MsgCreateSpotLimitOrder.py} (100%) rename examples/chain_client/exchange/{7_MsgCreateSpotMarketOrder.py => 4_MsgCreateSpotMarketOrder.py} (100%) rename examples/chain_client/exchange/{8_MsgCancelSpotOrder.py => 5_MsgCancelSpotOrder.py} (100%) rename examples/chain_client/exchange/{11_MsgCreateDerivativeMarketOrder.py => 6_MsgCreateDerivativeLimitOrder.py} (100%) rename examples/chain_client/exchange/{10_MsgCreateDerivativeLimitOrder.py => 7_MsgCreateDerivativeMarketOrder.py} (100%) rename examples/chain_client/exchange/{12_MsgCancelDerivativeOrder.py => 8_MsgCancelDerivativeOrder.py} (100%) rename examples/chain_client/exchange/{2_MsgWithdraw.py => 9_MsgWithdraw.py} (100%) diff --git a/examples/chain_client/exchange/17_MsgSubaccountTransfer.py b/examples/chain_client/exchange/10_MsgSubaccountTransfer.py similarity index 100% rename from examples/chain_client/exchange/17_MsgSubaccountTransfer.py rename to examples/chain_client/exchange/10_MsgSubaccountTransfer.py diff --git a/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py b/examples/chain_client/exchange/11_MsgBatchUpdateOrders.py similarity index 100% rename from examples/chain_client/exchange/9_MsgBatchUpdateOrders.py rename to examples/chain_client/exchange/11_MsgBatchUpdateOrders.py diff --git a/examples/chain_client/exchange/21_MsgRewardsOptOut.py b/examples/chain_client/exchange/12_MsgRewardsOptOut.py similarity index 100% rename from examples/chain_client/exchange/21_MsgRewardsOptOut.py rename to examples/chain_client/exchange/12_MsgRewardsOptOut.py diff --git a/examples/chain_client/exchange/18_MsgExternalTransfer.py b/examples/chain_client/exchange/15_ExternalTransfer.py similarity index 100% rename from examples/chain_client/exchange/18_MsgExternalTransfer.py rename to examples/chain_client/exchange/15_ExternalTransfer.py diff --git a/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py similarity index 100% rename from examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py rename to examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py diff --git a/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py similarity index 100% rename from examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py rename to examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py diff --git a/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py similarity index 100% rename from examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py rename to examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py diff --git a/examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py b/examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py similarity index 100% rename from examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py rename to examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py diff --git a/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py b/examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py similarity index 100% rename from examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py rename to examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py diff --git a/examples/chain_client/exchange/8_MsgCancelSpotOrder.py b/examples/chain_client/exchange/5_MsgCancelSpotOrder.py similarity index 100% rename from examples/chain_client/exchange/8_MsgCancelSpotOrder.py rename to examples/chain_client/exchange/5_MsgCancelSpotOrder.py diff --git a/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py similarity index 100% rename from examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py rename to examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py diff --git a/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py similarity index 100% rename from examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py rename to examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py diff --git a/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py b/examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py similarity index 100% rename from examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py rename to examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py diff --git a/examples/chain_client/exchange/2_MsgWithdraw.py b/examples/chain_client/exchange/9_MsgWithdraw.py similarity index 100% rename from examples/chain_client/exchange/2_MsgWithdraw.py rename to examples/chain_client/exchange/9_MsgWithdraw.py From 4725ad29a50e623fe8068be8d3834bba501328f3 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 27 Feb 2024 10:03:11 -0300 Subject: [PATCH 39/44] (feat) Added support for all chain exchange module messages in Composer. Added unit tests for new messages. Refactored example scripts to move them into separated subfolders for each module. --- ...eMarketOrder.py => 10_MsgCreateDerivativeLimitOrder.py} | 0 ...eLimitOrder.py => 11_MsgCreateDerivativeMarketOrder.py} | 7 ++++--- ...elDerivativeOrder.py => 12_MsgCancelDerivativeOrder.py} | 0 ...imitOrder.py => 14_MsgCreateBinaryOptionsLimitOrder.py} | 0 ...ketOrder.py => 15_MsgCreateBinaryOptionsMarketOrder.py} | 0 ...ryOptionsOrder.py => 16_MsgCancelBinaryOptionsOrder.py} | 0 ...sgSubaccountTransfer.py => 17_MsgSubaccountTransfer.py} | 0 .../{15_ExternalTransfer.py => 18_MsgExternalTransfer.py} | 0 .../{12_MsgRewardsOptOut.py => 21_MsgRewardsOptOut.py} | 0 .../exchange/{9_MsgWithdraw.py => 2_MsgWithdraw.py} | 0 ...reateSpotLimitOrder.py => 6_MsgCreateSpotLimitOrder.py} | 0 ...ateSpotMarketOrder.py => 7_MsgCreateSpotMarketOrder.py} | 0 .../{5_MsgCancelSpotOrder.py => 8_MsgCancelSpotOrder.py} | 0 ...1_MsgBatchUpdateOrders.py => 9_MsgBatchUpdateOrders.py} | 0 14 files changed, 4 insertions(+), 3 deletions(-) rename examples/chain_client/exchange/{7_MsgCreateDerivativeMarketOrder.py => 10_MsgCreateDerivativeLimitOrder.py} (100%) rename examples/chain_client/exchange/{6_MsgCreateDerivativeLimitOrder.py => 11_MsgCreateDerivativeMarketOrder.py} (93%) rename examples/chain_client/exchange/{8_MsgCancelDerivativeOrder.py => 12_MsgCancelDerivativeOrder.py} (100%) rename examples/chain_client/exchange/{16_MsgCreateBinaryOptionsLimitOrder.py => 14_MsgCreateBinaryOptionsLimitOrder.py} (100%) rename examples/chain_client/exchange/{17_MsgCreateBinaryOptionsMarketOrder.py => 15_MsgCreateBinaryOptionsMarketOrder.py} (100%) rename examples/chain_client/exchange/{18_MsgCancelBinaryOptionsOrder.py => 16_MsgCancelBinaryOptionsOrder.py} (100%) rename examples/chain_client/exchange/{10_MsgSubaccountTransfer.py => 17_MsgSubaccountTransfer.py} (100%) rename examples/chain_client/exchange/{15_ExternalTransfer.py => 18_MsgExternalTransfer.py} (100%) rename examples/chain_client/exchange/{12_MsgRewardsOptOut.py => 21_MsgRewardsOptOut.py} (100%) rename examples/chain_client/exchange/{9_MsgWithdraw.py => 2_MsgWithdraw.py} (100%) rename examples/chain_client/exchange/{3_MsgCreateSpotLimitOrder.py => 6_MsgCreateSpotLimitOrder.py} (100%) rename examples/chain_client/exchange/{4_MsgCreateSpotMarketOrder.py => 7_MsgCreateSpotMarketOrder.py} (100%) rename examples/chain_client/exchange/{5_MsgCancelSpotOrder.py => 8_MsgCancelSpotOrder.py} (100%) rename examples/chain_client/exchange/{11_MsgBatchUpdateOrders.py => 9_MsgBatchUpdateOrders.py} (100%) diff --git a/examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py b/examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py similarity index 100% rename from examples/chain_client/exchange/7_MsgCreateDerivativeMarketOrder.py rename to examples/chain_client/exchange/10_MsgCreateDerivativeLimitOrder.py diff --git a/examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py b/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py similarity index 93% rename from examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py rename to examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py index dfedf6d6..3b31e591 100644 --- a/examples/chain_client/exchange/6_MsgCreateDerivativeLimitOrder.py +++ b/examples/chain_client/exchange/11_MsgCreateDerivativeMarketOrder.py @@ -37,16 +37,17 @@ async def main() -> None: fee_recipient = "inj1hkhdaj2a2clmq5jq6mspsggqs32vynpk228q3r" # prepare tx msg - msg = composer.msg_create_derivative_market_order( + msg = composer.msg_create_derivative_limit_order( sender=address.to_acc_bech32(), market_id=market_id, subaccount_id=subaccount_id, fee_recipient=fee_recipient, price=Decimal(50000), - quantity=Decimal(0.01), + quantity=Decimal(0.1), margin=composer.calculate_margin( - quantity=Decimal(0.01), price=Decimal(50000), leverage=Decimal(3), is_reduce_only=False + quantity=Decimal(0.1), price=Decimal(50000), leverage=Decimal(1), is_reduce_only=False ), + order_type="BUY", cid=str(uuid.uuid4()), ) diff --git a/examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py b/examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py similarity index 100% rename from examples/chain_client/exchange/8_MsgCancelDerivativeOrder.py rename to examples/chain_client/exchange/12_MsgCancelDerivativeOrder.py diff --git a/examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py b/examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py similarity index 100% rename from examples/chain_client/exchange/16_MsgCreateBinaryOptionsLimitOrder.py rename to examples/chain_client/exchange/14_MsgCreateBinaryOptionsLimitOrder.py diff --git a/examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py b/examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py similarity index 100% rename from examples/chain_client/exchange/17_MsgCreateBinaryOptionsMarketOrder.py rename to examples/chain_client/exchange/15_MsgCreateBinaryOptionsMarketOrder.py diff --git a/examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py b/examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py similarity index 100% rename from examples/chain_client/exchange/18_MsgCancelBinaryOptionsOrder.py rename to examples/chain_client/exchange/16_MsgCancelBinaryOptionsOrder.py diff --git a/examples/chain_client/exchange/10_MsgSubaccountTransfer.py b/examples/chain_client/exchange/17_MsgSubaccountTransfer.py similarity index 100% rename from examples/chain_client/exchange/10_MsgSubaccountTransfer.py rename to examples/chain_client/exchange/17_MsgSubaccountTransfer.py diff --git a/examples/chain_client/exchange/15_ExternalTransfer.py b/examples/chain_client/exchange/18_MsgExternalTransfer.py similarity index 100% rename from examples/chain_client/exchange/15_ExternalTransfer.py rename to examples/chain_client/exchange/18_MsgExternalTransfer.py diff --git a/examples/chain_client/exchange/12_MsgRewardsOptOut.py b/examples/chain_client/exchange/21_MsgRewardsOptOut.py similarity index 100% rename from examples/chain_client/exchange/12_MsgRewardsOptOut.py rename to examples/chain_client/exchange/21_MsgRewardsOptOut.py diff --git a/examples/chain_client/exchange/9_MsgWithdraw.py b/examples/chain_client/exchange/2_MsgWithdraw.py similarity index 100% rename from examples/chain_client/exchange/9_MsgWithdraw.py rename to examples/chain_client/exchange/2_MsgWithdraw.py diff --git a/examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py b/examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py similarity index 100% rename from examples/chain_client/exchange/3_MsgCreateSpotLimitOrder.py rename to examples/chain_client/exchange/6_MsgCreateSpotLimitOrder.py diff --git a/examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py b/examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py similarity index 100% rename from examples/chain_client/exchange/4_MsgCreateSpotMarketOrder.py rename to examples/chain_client/exchange/7_MsgCreateSpotMarketOrder.py diff --git a/examples/chain_client/exchange/5_MsgCancelSpotOrder.py b/examples/chain_client/exchange/8_MsgCancelSpotOrder.py similarity index 100% rename from examples/chain_client/exchange/5_MsgCancelSpotOrder.py rename to examples/chain_client/exchange/8_MsgCancelSpotOrder.py diff --git a/examples/chain_client/exchange/11_MsgBatchUpdateOrders.py b/examples/chain_client/exchange/9_MsgBatchUpdateOrders.py similarity index 100% rename from examples/chain_client/exchange/11_MsgBatchUpdateOrders.py rename to examples/chain_client/exchange/9_MsgBatchUpdateOrders.py From 1b6953a4660603d4a874c99e5f00eede24d50a12 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 27 Feb 2024 13:11:47 -0300 Subject: [PATCH 40/44] (fix) Fix in CodeRabbit confir YAML file --- .coderabbit.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 8e534ba3..930db111 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -4,3 +4,5 @@ reviews: - "master" - "dev" - "feat/.*" +chat: + auto_reply: true From 5e8b13bbfa8313e04bc56168ed2f8a68320878d1 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 5 Mar 2024 12:19:29 -0300 Subject: [PATCH 41/44] (feat) Added support for a missing endpoint in the chain exchange module: TradeRewardCampaign --- .../exchange/query/41_TradeRewardCampaign.py | 32 +++++ ...ntInfo.py => 42_FeeDiscountAccountInfo.py} | 0 ...tSchedule.py => 43_FeeDiscountSchedule.py} | 0 ...eMismatches.py => 44_BalanceMismatches.py} | 0 ...Holds.py => 45_BalanceWithBalanceHolds.py} | 0 ...ics.py => 46_FeeDiscountTierStatistics.py} | 0 ...MitoVaultInfos.py => 47_MitoVaultInfos.py} | 0 ...mVault.py => 48_QueryMarketIDFromVault.py} | 0 ...ecords.py => 49_HistoricalTradeRecords.py} | 0 ...OfRewards.py => 50_IsOptedOutOfRewards.py} | 0 ...nts.py => 51_OptedOutOfRewardsAccounts.py} | 0 ...etVolatility.py => 52_MarketVolatility.py} | 0 ...sMarkets.py => 53_BinaryOptionsMarkets.py} | 0 ...> 54_TraderDerivativeConditionalOrders.py} | 0 ... 55_MarketAtomicExecutionFeeMultiplier.py} | 0 pyinjective/async_client.py | 3 + .../chain/grpc/chain_grpc_exchange_api.py | 6 + .../configurable_exchange_query_servicer.py | 6 + .../grpc/test_chain_grpc_exchange_api.py | 113 ++++++++++++++++++ 19 files changed, 160 insertions(+) create mode 100644 examples/chain_client/exchange/query/41_TradeRewardCampaign.py rename examples/chain_client/exchange/query/{41_FeeDiscountAccountInfo.py => 42_FeeDiscountAccountInfo.py} (100%) rename examples/chain_client/exchange/query/{42_FeeDiscountSchedule.py => 43_FeeDiscountSchedule.py} (100%) rename examples/chain_client/exchange/query/{43_BalanceMismatches.py => 44_BalanceMismatches.py} (100%) rename examples/chain_client/exchange/query/{44_BalanceWithBalanceHolds.py => 45_BalanceWithBalanceHolds.py} (100%) rename examples/chain_client/exchange/query/{45_FeeDiscountTierStatistics.py => 46_FeeDiscountTierStatistics.py} (100%) rename examples/chain_client/exchange/query/{46_MitoVaultInfos.py => 47_MitoVaultInfos.py} (100%) rename examples/chain_client/exchange/query/{47_QueryMarketIDFromVault.py => 48_QueryMarketIDFromVault.py} (100%) rename examples/chain_client/exchange/query/{48_HistoricalTradeRecords.py => 49_HistoricalTradeRecords.py} (100%) rename examples/chain_client/exchange/query/{49_IsOptedOutOfRewards.py => 50_IsOptedOutOfRewards.py} (100%) rename examples/chain_client/exchange/query/{50_OptedOutOfRewardsAccounts.py => 51_OptedOutOfRewardsAccounts.py} (100%) rename examples/chain_client/exchange/query/{51_MarketVolatility.py => 52_MarketVolatility.py} (100%) rename examples/chain_client/exchange/query/{52_BinaryOptionsMarkets.py => 53_BinaryOptionsMarkets.py} (100%) rename examples/chain_client/exchange/query/{53_TraderDerivativeConditionalOrders.py => 54_TraderDerivativeConditionalOrders.py} (100%) rename examples/chain_client/exchange/query/{54_MarketAtomicExecutionFeeMultiplier.py => 55_MarketAtomicExecutionFeeMultiplier.py} (100%) diff --git a/examples/chain_client/exchange/query/41_TradeRewardCampaign.py b/examples/chain_client/exchange/query/41_TradeRewardCampaign.py new file mode 100644 index 00000000..33e45a7e --- /dev/null +++ b/examples/chain_client/exchange/query/41_TradeRewardCampaign.py @@ -0,0 +1,32 @@ +import asyncio +import os + +import dotenv + +from pyinjective import PrivateKey +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + dotenv.load_dotenv() + configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") + + # select network: local, testnet, mainnet + network = Network.testnet() + + # initialize grpc client + client = AsyncClient(network) + + # load account + priv_key = PrivateKey.from_hex(configured_private_key) + pub_key = priv_key.to_public_key() + address = pub_key.to_address() + await client.fetch_account(address.to_acc_bech32()) + + campaign = await client.fetch_trade_reward_campaign() + print(campaign) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py b/examples/chain_client/exchange/query/42_FeeDiscountAccountInfo.py similarity index 100% rename from examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py rename to examples/chain_client/exchange/query/42_FeeDiscountAccountInfo.py diff --git a/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py b/examples/chain_client/exchange/query/43_FeeDiscountSchedule.py similarity index 100% rename from examples/chain_client/exchange/query/42_FeeDiscountSchedule.py rename to examples/chain_client/exchange/query/43_FeeDiscountSchedule.py diff --git a/examples/chain_client/exchange/query/43_BalanceMismatches.py b/examples/chain_client/exchange/query/44_BalanceMismatches.py similarity index 100% rename from examples/chain_client/exchange/query/43_BalanceMismatches.py rename to examples/chain_client/exchange/query/44_BalanceMismatches.py diff --git a/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py b/examples/chain_client/exchange/query/45_BalanceWithBalanceHolds.py similarity index 100% rename from examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py rename to examples/chain_client/exchange/query/45_BalanceWithBalanceHolds.py diff --git a/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py b/examples/chain_client/exchange/query/46_FeeDiscountTierStatistics.py similarity index 100% rename from examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py rename to examples/chain_client/exchange/query/46_FeeDiscountTierStatistics.py diff --git a/examples/chain_client/exchange/query/46_MitoVaultInfos.py b/examples/chain_client/exchange/query/47_MitoVaultInfos.py similarity index 100% rename from examples/chain_client/exchange/query/46_MitoVaultInfos.py rename to examples/chain_client/exchange/query/47_MitoVaultInfos.py diff --git a/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py b/examples/chain_client/exchange/query/48_QueryMarketIDFromVault.py similarity index 100% rename from examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py rename to examples/chain_client/exchange/query/48_QueryMarketIDFromVault.py diff --git a/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py b/examples/chain_client/exchange/query/49_HistoricalTradeRecords.py similarity index 100% rename from examples/chain_client/exchange/query/48_HistoricalTradeRecords.py rename to examples/chain_client/exchange/query/49_HistoricalTradeRecords.py diff --git a/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py b/examples/chain_client/exchange/query/50_IsOptedOutOfRewards.py similarity index 100% rename from examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py rename to examples/chain_client/exchange/query/50_IsOptedOutOfRewards.py diff --git a/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py b/examples/chain_client/exchange/query/51_OptedOutOfRewardsAccounts.py similarity index 100% rename from examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py rename to examples/chain_client/exchange/query/51_OptedOutOfRewardsAccounts.py diff --git a/examples/chain_client/exchange/query/51_MarketVolatility.py b/examples/chain_client/exchange/query/52_MarketVolatility.py similarity index 100% rename from examples/chain_client/exchange/query/51_MarketVolatility.py rename to examples/chain_client/exchange/query/52_MarketVolatility.py diff --git a/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py b/examples/chain_client/exchange/query/53_BinaryOptionsMarkets.py similarity index 100% rename from examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py rename to examples/chain_client/exchange/query/53_BinaryOptionsMarkets.py diff --git a/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py b/examples/chain_client/exchange/query/54_TraderDerivativeConditionalOrders.py similarity index 100% rename from examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py rename to examples/chain_client/exchange/query/54_TraderDerivativeConditionalOrders.py diff --git a/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py b/examples/chain_client/exchange/query/55_MarketAtomicExecutionFeeMultiplier.py similarity index 100% rename from examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py rename to examples/chain_client/exchange/query/55_MarketAtomicExecutionFeeMultiplier.py diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index 0af37da0..d684a234 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -965,6 +965,9 @@ async def fetch_pending_trade_reward_points( pending_pool_timestamp=pending_pool_timestamp, ) + async def fetch_trade_reward_campaign(self) -> Dict[str, Any]: + return await self.chain_exchange_api.fetch_trade_reward_campaign() + async def fetch_fee_discount_account_info(self, account: str) -> Dict[str, Any]: return await self.chain_exchange_api.fetch_fee_discount_account_info(account=account) diff --git a/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py b/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py index 217c0d34..b79e8569 100644 --- a/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py +++ b/pyinjective/client/chain/grpc/chain_grpc_exchange_api.py @@ -451,6 +451,12 @@ async def fetch_pending_trade_reward_points( return response + async def fetch_trade_reward_campaign(self) -> Dict[str, Any]: + request = exchange_query_pb.QueryTradeRewardCampaignRequest() + response = await self._execute_call(call=self._stub.TradeRewardCampaign, request=request) + + return response + async def fetch_fee_discount_account_info( self, account: str, diff --git a/tests/client/chain/grpc/configurable_exchange_query_servicer.py b/tests/client/chain/grpc/configurable_exchange_query_servicer.py index 267b08ce..23ded1de 100644 --- a/tests/client/chain/grpc/configurable_exchange_query_servicer.py +++ b/tests/client/chain/grpc/configurable_exchange_query_servicer.py @@ -50,6 +50,7 @@ def __init__(self): self.subaccount_order_metadata_responses = deque() self.trade_reward_points_responses = deque() self.pending_trade_reward_points_responses = deque() + self.trade_reward_campaign_responses = deque() self.fee_discount_account_info_responses = deque() self.fee_discount_schedule_responses = deque() self.balance_mismatches_responses = deque() @@ -256,6 +257,11 @@ async def PendingTradeRewardPoints( ): return self.pending_trade_reward_points_responses.pop() + async def TradeRewardCampaign( + self, request: exchange_query_pb.QueryTradeRewardCampaignRequest, context=None, metadata=None + ): + return self.trade_reward_campaign_responses.pop() + async def FeeDiscountAccountInfo( self, request: exchange_query_pb.QueryFeeDiscountAccountInfoRequest, context=None, metadata=None ): diff --git a/tests/client/chain/grpc/test_chain_grpc_exchange_api.py b/tests/client/chain/grpc/test_chain_grpc_exchange_api.py index 54393a94..7ff77bbc 100644 --- a/tests/client/chain/grpc/test_chain_grpc_exchange_api.py +++ b/tests/client/chain/grpc/test_chain_grpc_exchange_api.py @@ -1909,6 +1909,119 @@ async def test_fetch_pending_trade_reward_points( assert trade_reward_points == expected_trade_reward_points + @pytest.mark.asyncio + async def test_fetch_trade_reward_campaign( + self, + exchange_servicer, + ): + spot_market_multiplier = exchange_pb.PointsMultiplier( + maker_points_multiplier="10.0", + taker_points_multiplier="5.0", + ) + derivative_market_multiplier = exchange_pb.PointsMultiplier( + maker_points_multiplier="9.0", + taker_points_multiplier="6.0", + ) + trading_reward_boost_info = exchange_pb.TradingRewardCampaignBoostInfo( + boosted_spot_market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00aaf7"], + spot_market_multipliers=[spot_market_multiplier], + boosted_derivative_market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6"], + derivative_market_multipliers=[derivative_market_multiplier], + ) + trading_reward_campaign_info = exchange_pb.TradingRewardCampaignInfo( + campaign_duration_seconds=3600, + quote_denoms=["peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5"], + trading_reward_boost_info=trading_reward_boost_info, + disqualified_market_ids=["0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00aaf7"], + ) + reward = coin_pb.Coin( + amount="1000000000000000000", + denom="inj", + ) + trading_reward_pool_campaign_schedule = exchange_pb.CampaignRewardPool( + start_timestamp=1708099200, + max_campaign_rewards=[reward], + ) + total_trade_reward_points = "40" + pending_reward = coin_pb.Coin( + amount="2000000000000000000", + denom="peggy0x87aB3B4C8661e07D6372361211B96ed4Dc36B1B5", + ) + pending_trading_reward_pool_campaign_schedule = exchange_pb.CampaignRewardPool( + start_timestamp=1709099200, + max_campaign_rewards=[pending_reward], + ) + pending_total_trade_reward_points = "80" + response = exchange_query_pb.QueryTradeRewardCampaignResponse( + trading_reward_campaign_info=trading_reward_campaign_info, + trading_reward_pool_campaign_schedule=[trading_reward_pool_campaign_schedule], + total_trade_reward_points=total_trade_reward_points, + pending_trading_reward_pool_campaign_schedule=[pending_trading_reward_pool_campaign_schedule], + pending_total_trade_reward_points=[pending_total_trade_reward_points], + ) + exchange_servicer.trade_reward_campaign_responses.append(response) + + network = Network.devnet() + channel = grpc.aio.insecure_channel(network.grpc_endpoint) + + api = ChainGrpcExchangeApi(channel=channel, metadata_provider=lambda: self._dummy_metadata_provider()) + api._stub = exchange_servicer + + trade_reward_campaign = await api.fetch_trade_reward_campaign() + expected_campaign = { + "tradingRewardCampaignInfo": { + "campaignDurationSeconds": str(trading_reward_campaign_info.campaign_duration_seconds), + "quoteDenoms": trading_reward_campaign_info.quote_denoms, + "tradingRewardBoostInfo": { + "boostedSpotMarketIds": ( + trading_reward_campaign_info.trading_reward_boost_info.boosted_spot_market_ids + ), + "spotMarketMultipliers": [ + { + "makerPointsMultiplier": spot_market_multiplier.maker_points_multiplier, + "takerPointsMultiplier": spot_market_multiplier.taker_points_multiplier, + }, + ], + "boostedDerivativeMarketIds": ( + trading_reward_campaign_info.trading_reward_boost_info.boosted_derivative_market_ids + ), + "derivativeMarketMultipliers": [ + { + "makerPointsMultiplier": derivative_market_multiplier.maker_points_multiplier, + "takerPointsMultiplier": derivative_market_multiplier.taker_points_multiplier, + }, + ], + }, + "disqualifiedMarketIds": trading_reward_campaign_info.disqualified_market_ids, + }, + "tradingRewardPoolCampaignSchedule": [ + { + "startTimestamp": str(trading_reward_pool_campaign_schedule.start_timestamp), + "maxCampaignRewards": [ + { + "amount": trading_reward_pool_campaign_schedule.max_campaign_rewards[0].amount, + "denom": trading_reward_pool_campaign_schedule.max_campaign_rewards[0].denom, + }, + ], + }, + ], + "totalTradeRewardPoints": total_trade_reward_points, + "pendingTradingRewardPoolCampaignSchedule": [ + { + "startTimestamp": str(pending_trading_reward_pool_campaign_schedule.start_timestamp), + "maxCampaignRewards": [ + { + "amount": pending_trading_reward_pool_campaign_schedule.max_campaign_rewards[0].amount, + "denom": pending_trading_reward_pool_campaign_schedule.max_campaign_rewards[0].denom, + }, + ], + }, + ], + "pendingTotalTradeRewardPoints": [pending_total_trade_reward_points], + } + + assert trade_reward_campaign == expected_campaign + @pytest.mark.asyncio async def test_fetch_fee_discount_account_info( self, From 13ff9a81e18b524ce3f4b0861a7896c7c16b6f7a Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 5 Mar 2024 12:48:11 -0300 Subject: [PATCH 42/44] (fix) Updated CHANGELOG.md file --- CHANGELOG.md | 6 + poetry.lock | 616 +++++++++++++++++++++++++-------------------------- 2 files changed, 314 insertions(+), 308 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6f16f42..876c5845 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## [1.4.0] - 2024-03-11 +### Added +- Added support for all queries and messages in the chain 'distribution' module +- Added support for all queries and messages in the chain 'exchange' module +- Use of python-dotenv in all example scripts to load private keys from a .env file + ## [1.3.1] - 2024-02-29 ### Changed - Updated cookie assistant logic to support the Indexer exchange server not using cookies and the chain server using them diff --git a/poetry.lock b/poetry.lock index 082dfb36..30d01a9d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -635,63 +635,63 @@ files = [ [[package]] name = "coverage" -version = "7.4.1" +version = "7.4.3" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:077d366e724f24fc02dbfe9d946534357fda71af9764ff99d73c3c596001bbd7"}, - {file = "coverage-7.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0193657651f5399d433c92f8ae264aff31fc1d066deee4b831549526433f3f61"}, - {file = "coverage-7.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d17bbc946f52ca67adf72a5ee783cd7cd3477f8f8796f59b4974a9b59cacc9ee"}, - {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3277f5fa7483c927fe3a7b017b39351610265308f5267ac6d4c2b64cc1d8d25"}, - {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dceb61d40cbfcf45f51e59933c784a50846dc03211054bd76b421a713dcdf19"}, - {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6008adeca04a445ea6ef31b2cbaf1d01d02986047606f7da266629afee982630"}, - {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c61f66d93d712f6e03369b6a7769233bfda880b12f417eefdd4f16d1deb2fc4c"}, - {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9bb62fac84d5f2ff523304e59e5c439955fb3b7f44e3d7b2085184db74d733b"}, - {file = "coverage-7.4.1-cp310-cp310-win32.whl", hash = "sha256:f86f368e1c7ce897bf2457b9eb61169a44e2ef797099fb5728482b8d69f3f016"}, - {file = "coverage-7.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:869b5046d41abfea3e381dd143407b0d29b8282a904a19cb908fa24d090cc018"}, - {file = "coverage-7.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8ffb498a83d7e0305968289441914154fb0ef5d8b3157df02a90c6695978295"}, - {file = "coverage-7.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3cacfaefe6089d477264001f90f55b7881ba615953414999c46cc9713ff93c8c"}, - {file = "coverage-7.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d6850e6e36e332d5511a48a251790ddc545e16e8beaf046c03985c69ccb2676"}, - {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18e961aa13b6d47f758cc5879383d27b5b3f3dcd9ce8cdbfdc2571fe86feb4dd"}, - {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfd1e1b9f0898817babf840b77ce9fe655ecbe8b1b327983df485b30df8cc011"}, - {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6b00e21f86598b6330f0019b40fb397e705135040dbedc2ca9a93c7441178e74"}, - {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:536d609c6963c50055bab766d9951b6c394759190d03311f3e9fcf194ca909e1"}, - {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7ac8f8eb153724f84885a1374999b7e45734bf93a87d8df1e7ce2146860edef6"}, - {file = "coverage-7.4.1-cp311-cp311-win32.whl", hash = "sha256:f3771b23bb3675a06f5d885c3630b1d01ea6cac9e84a01aaf5508706dba546c5"}, - {file = "coverage-7.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:9d2f9d4cc2a53b38cabc2d6d80f7f9b7e3da26b2f53d48f05876fef7956b6968"}, - {file = "coverage-7.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f68ef3660677e6624c8cace943e4765545f8191313a07288a53d3da188bd8581"}, - {file = "coverage-7.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23b27b8a698e749b61809fb637eb98ebf0e505710ec46a8aa6f1be7dc0dc43a6"}, - {file = "coverage-7.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e3424c554391dc9ef4a92ad28665756566a28fecf47308f91841f6c49288e66"}, - {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0860a348bf7004c812c8368d1fc7f77fe8e4c095d661a579196a9533778e156"}, - {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe558371c1bdf3b8fa03e097c523fb9645b8730399c14fe7721ee9c9e2a545d3"}, - {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3468cc8720402af37b6c6e7e2a9cdb9f6c16c728638a2ebc768ba1ef6f26c3a1"}, - {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:02f2edb575d62172aa28fe00efe821ae31f25dc3d589055b3fb64d51e52e4ab1"}, - {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ca6e61dc52f601d1d224526360cdeab0d0712ec104a2ce6cc5ccef6ed9a233bc"}, - {file = "coverage-7.4.1-cp312-cp312-win32.whl", hash = "sha256:ca7b26a5e456a843b9b6683eada193fc1f65c761b3a473941efe5a291f604c74"}, - {file = "coverage-7.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:85ccc5fa54c2ed64bd91ed3b4a627b9cce04646a659512a051fa82a92c04a448"}, - {file = "coverage-7.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8bdb0285a0202888d19ec6b6d23d5990410decb932b709f2b0dfe216d031d218"}, - {file = "coverage-7.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:918440dea04521f499721c039863ef95433314b1db00ff826a02580c1f503e45"}, - {file = "coverage-7.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:379d4c7abad5afbe9d88cc31ea8ca262296480a86af945b08214eb1a556a3e4d"}, - {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b094116f0b6155e36a304ff912f89bbb5067157aff5f94060ff20bbabdc8da06"}, - {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f5968608b1fe2a1d00d01ad1017ee27efd99b3437e08b83ded9b7af3f6f766"}, - {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:10e88e7f41e6197ea0429ae18f21ff521d4f4490aa33048f6c6f94c6045a6a75"}, - {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a4a3907011d39dbc3e37bdc5df0a8c93853c369039b59efa33a7b6669de04c60"}, - {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d224f0c4c9c98290a6990259073f496fcec1b5cc613eecbd22786d398ded3ad"}, - {file = "coverage-7.4.1-cp38-cp38-win32.whl", hash = "sha256:23f5881362dcb0e1a92b84b3c2809bdc90db892332daab81ad8f642d8ed55042"}, - {file = "coverage-7.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:a07f61fc452c43cd5328b392e52555f7d1952400a1ad09086c4a8addccbd138d"}, - {file = "coverage-7.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8e738a492b6221f8dcf281b67129510835461132b03024830ac0e554311a5c54"}, - {file = "coverage-7.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46342fed0fff72efcda77040b14728049200cbba1279e0bf1188f1f2078c1d70"}, - {file = "coverage-7.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9641e21670c68c7e57d2053ddf6c443e4f0a6e18e547e86af3fad0795414a628"}, - {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aeb2c2688ed93b027eb0d26aa188ada34acb22dceea256d76390eea135083950"}, - {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d12c923757de24e4e2110cf8832d83a886a4cf215c6e61ed506006872b43a6d1"}, - {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0491275c3b9971cdbd28a4595c2cb5838f08036bca31765bad5e17edf900b2c7"}, - {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8dfc5e195bbef80aabd81596ef52a1277ee7143fe419efc3c4d8ba2754671756"}, - {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a78b656a4d12b0490ca72651fe4d9f5e07e3c6461063a9b6265ee45eb2bdd35"}, - {file = "coverage-7.4.1-cp39-cp39-win32.whl", hash = "sha256:f90515974b39f4dea2f27c0959688621b46d96d5a626cf9c53dbc653a895c05c"}, - {file = "coverage-7.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:64e723ca82a84053dd7bfcc986bdb34af8d9da83c521c19d6b472bc6880e191a"}, - {file = "coverage-7.4.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:32a8d985462e37cfdab611a6f95b09d7c091d07668fdc26e47a725ee575fe166"}, - {file = "coverage-7.4.1.tar.gz", hash = "sha256:1ed4b95480952b1a26d863e546fa5094564aa0065e1e5f0d4d0041f293251d04"}, + {file = "coverage-7.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8580b827d4746d47294c0e0b92854c85a92c2227927433998f0d3320ae8a71b6"}, + {file = "coverage-7.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:718187eeb9849fc6cc23e0d9b092bc2348821c5e1a901c9f8975df0bc785bfd4"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:767b35c3a246bcb55b8044fd3a43b8cd553dd1f9f2c1eeb87a302b1f8daa0524"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae7f19afe0cce50039e2c782bff379c7e347cba335429678450b8fe81c4ef96d"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba3a8aaed13770e970b3df46980cb068d1c24af1a1968b7818b69af8c4347efb"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ee866acc0861caebb4f2ab79f0b94dbfbdbfadc19f82e6e9c93930f74e11d7a0"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:506edb1dd49e13a2d4cac6a5173317b82a23c9d6e8df63efb4f0380de0fbccbc"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd6545d97c98a192c5ac995d21c894b581f1fd14cf389be90724d21808b657e2"}, + {file = "coverage-7.4.3-cp310-cp310-win32.whl", hash = "sha256:f6a09b360d67e589236a44f0c39218a8efba2593b6abdccc300a8862cffc2f94"}, + {file = "coverage-7.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:18d90523ce7553dd0b7e23cbb28865db23cddfd683a38fb224115f7826de78d0"}, + {file = "coverage-7.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbbe5e739d45a52f3200a771c6d2c7acf89eb2524890a4a3aa1a7fa0695d2a47"}, + {file = "coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:489763b2d037b164846ebac0cbd368b8a4ca56385c4090807ff9fad817de4113"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451f433ad901b3bb00184d83fd83d135fb682d780b38af7944c9faeecb1e0bfe"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc66e222cf4c719fe7722a403888b1f5e1682d1679bd780e2b26c18bb648cdc"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ec74cfef2d985e145baae90d9b1b32f85e1741b04cd967aaf9cfa84c1334f3"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:abbbd8093c5229c72d4c2926afaee0e6e3140de69d5dcd918b2921f2f0c8baba"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:35eb581efdacf7b7422af677b92170da4ef34500467381e805944a3201df2079"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8249b1c7334be8f8c3abcaaa996e1e4927b0e5a23b65f5bf6cfe3180d8ca7840"}, + {file = "coverage-7.4.3-cp311-cp311-win32.whl", hash = "sha256:cf30900aa1ba595312ae41978b95e256e419d8a823af79ce670835409fc02ad3"}, + {file = "coverage-7.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:18c7320695c949de11a351742ee001849912fd57e62a706d83dfc1581897fa2e"}, + {file = "coverage-7.4.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b51bfc348925e92a9bd9b2e48dad13431b57011fd1038f08316e6bf1df107d10"}, + {file = "coverage-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6cdecaedea1ea9e033d8adf6a0ab11107b49571bbb9737175444cea6eb72328"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2eccb883368f9e972e216c7b4c7c06cabda925b5f06dde0650281cb7666a30"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c00cdc8fa4e50e1cc1f941a7f2e3e0f26cb2a1233c9696f26963ff58445bac7"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4a8dd3dcf4cbd3165737358e4d7dfbd9d59902ad11e3b15eebb6393b0446e"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:062b0a75d9261e2f9c6d071753f7eef0fc9caf3a2c82d36d76667ba7b6470003"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ebe7c9e67a2d15fa97b77ea6571ce5e1e1f6b0db71d1d5e96f8d2bf134303c1d"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0a120238dd71c68484f02562f6d446d736adcc6ca0993712289b102705a9a3a"}, + {file = "coverage-7.4.3-cp312-cp312-win32.whl", hash = "sha256:37389611ba54fd6d278fde86eb2c013c8e50232e38f5c68235d09d0a3f8aa352"}, + {file = "coverage-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:d25b937a5d9ffa857d41be042b4238dd61db888533b53bc76dc082cb5a15e914"}, + {file = "coverage-7.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:28ca2098939eabab044ad68850aac8f8db6bf0b29bc7f2887d05889b17346454"}, + {file = "coverage-7.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:280459f0a03cecbe8800786cdc23067a8fc64c0bd51dc614008d9c36e1659d7e"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c0cdedd3500e0511eac1517bf560149764b7d8e65cb800d8bf1c63ebf39edd2"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a9babb9466fe1da12417a4aed923e90124a534736de6201794a3aea9d98484e"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dec9de46a33cf2dd87a5254af095a409ea3bf952d85ad339751e7de6d962cde6"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:16bae383a9cc5abab9bb05c10a3e5a52e0a788325dc9ba8499e821885928968c"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2c854ce44e1ee31bda4e318af1dbcfc929026d12c5ed030095ad98197eeeaed0"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ce8c50520f57ec57aa21a63ea4f325c7b657386b3f02ccaedeccf9ebe27686e1"}, + {file = "coverage-7.4.3-cp38-cp38-win32.whl", hash = "sha256:708a3369dcf055c00ddeeaa2b20f0dd1ce664eeabde6623e516c5228b753654f"}, + {file = "coverage-7.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:1bf25fbca0c8d121a3e92a2a0555c7e5bc981aee5c3fdaf4bb7809f410f696b9"}, + {file = "coverage-7.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b253094dbe1b431d3a4ac2f053b6d7ede2664ac559705a704f621742e034f1f"}, + {file = "coverage-7.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77fbfc5720cceac9c200054b9fab50cb2a7d79660609200ab83f5db96162d20c"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6679060424faa9c11808598504c3ab472de4531c571ab2befa32f4971835788e"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4af154d617c875b52651dd8dd17a31270c495082f3d55f6128e7629658d63765"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8640f1fde5e1b8e3439fe482cdc2b0bb6c329f4bb161927c28d2e8879c6029ee"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:69b9f6f66c0af29642e73a520b6fed25ff9fd69a25975ebe6acb297234eda501"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0842571634f39016a6c03e9d4aba502be652a6e4455fadb73cd3a3a49173e38f"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a78ed23b08e8ab524551f52953a8a05d61c3a760781762aac49f8de6eede8c45"}, + {file = "coverage-7.4.3-cp39-cp39-win32.whl", hash = "sha256:c0524de3ff096e15fcbfe8f056fdb4ea0bf497d584454f344d59fce069d3e6e9"}, + {file = "coverage-7.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:0209a6369ccce576b43bb227dc8322d8ef9e323d089c6f3f26a597b09cb4d2aa"}, + {file = "coverage-7.4.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:7cbde573904625509a3f37b6fecea974e363460b556a627c60dc2f47e2fffa51"}, + {file = "coverage-7.4.3.tar.gz", hash = "sha256:276f6077a5c61447a48d133ed13e759c09e62aff0dc84274a68dc18660104d52"}, ] [package.dependencies] @@ -899,13 +899,13 @@ files = [ [[package]] name = "eth-abi" -version = "5.0.0" +version = "5.0.1" description = "eth_abi: Python utilities for working with Ethereum ABI definitions, especially encoding and decoding" optional = false python-versions = ">=3.8, <4" files = [ - {file = "eth_abi-5.0.0-py3-none-any.whl", hash = "sha256:936a715d7366ac13cac665cbdaf01cc4aabbe8c2d810d716287a9634f9665e01"}, - {file = "eth_abi-5.0.0.tar.gz", hash = "sha256:89c4454d794d9ed92ad5cb2794698c5cee6b7b3ca6009187d0e282adc7f9b6dc"}, + {file = "eth_abi-5.0.1-py3-none-any.whl", hash = "sha256:521960d8b4beee514958e1774951dc6b48176aa274e3bd8b166f6921453047ef"}, + {file = "eth_abi-5.0.1.tar.gz", hash = "sha256:e9425110c6120c585c9f0db2e8a33d76c4b886b148a65e68fc0035d3917a3b9c"}, ] [package.dependencies] @@ -914,9 +914,9 @@ eth-utils = ">=2.0.0" parsimonious = ">=0.9.0,<0.10.0" [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -test = ["eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-xdist (>=2.4.0)"] +test = ["eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.0.0)", "pytest-xdist (>=2.4.0)"] tools = ["hypothesis (>=4.18.2,<5.0.0)"] [[package]] @@ -948,13 +948,13 @@ test = ["coverage", "hypothesis (>=4.18.0,<5)", "pytest (>=7.0.0)", "pytest-xdis [[package]] name = "eth-hash" -version = "0.6.0" +version = "0.7.0" description = "eth-hash: The Ethereum hashing function, keccak256, sometimes (erroneously) called sha3" optional = false python-versions = ">=3.8, <4" files = [ - {file = "eth-hash-0.6.0.tar.gz", hash = "sha256:ae72889e60db6acbb3872c288cfa02ed157f4c27630fcd7f9c8442302c31e478"}, - {file = "eth_hash-0.6.0-py3-none-any.whl", hash = "sha256:9f8daaa345764f8871dc461855049ac54ae4291d780279bce6fce7f24e3f17d3"}, + {file = "eth-hash-0.7.0.tar.gz", hash = "sha256:bacdc705bfd85dadd055ecd35fd1b4f846b671add101427e089a4ca2e8db310a"}, + {file = "eth_hash-0.7.0-py3-none-any.whl", hash = "sha256:b8d5a230a2b251f4a291e3164a23a14057c4a6de4b0aa4a16fa4dc9161b57e2f"}, ] [package.dependencies] @@ -969,13 +969,13 @@ test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-keyfile" -version = "0.7.0" +version = "0.8.0" description = "eth-keyfile: A library for handling the encrypted keyfiles used to store ethereum private keys" optional = false python-versions = ">=3.8, <4" files = [ - {file = "eth-keyfile-0.7.0.tar.gz", hash = "sha256:6bdb8110c3a50439deb68a04c93c9d5ddd5402353bfae1bf4cfca1d6dff14fcf"}, - {file = "eth_keyfile-0.7.0-py3-none-any.whl", hash = "sha256:6a89b231a2fe250c3a8f924f2695bb9cce33ddd0d6f7ebbcdacd183d7f83d537"}, + {file = "eth-keyfile-0.8.0.tar.gz", hash = "sha256:02e3c2e564c7403b92db3fef8ecae3d21123b15787daecd5b643a57369c530f9"}, + {file = "eth_keyfile-0.8.0-py3-none-any.whl", hash = "sha256:9e09f5bc97c8309876c06bdea7a94f0051c25ba3109b5df37afb815418322efe"}, ] [package.dependencies] @@ -1230,135 +1230,135 @@ files = [ [[package]] name = "grpcio" -version = "1.60.1" +version = "1.62.0" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.7" files = [ - {file = "grpcio-1.60.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:14e8f2c84c0832773fb3958240c69def72357bc11392571f87b2d7b91e0bb092"}, - {file = "grpcio-1.60.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:33aed0a431f5befeffd9d346b0fa44b2c01aa4aeae5ea5b2c03d3e25e0071216"}, - {file = "grpcio-1.60.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:fead980fbc68512dfd4e0c7b1f5754c2a8e5015a04dea454b9cada54a8423525"}, - {file = "grpcio-1.60.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:082081e6a36b6eb5cf0fd9a897fe777dbb3802176ffd08e3ec6567edd85bc104"}, - {file = "grpcio-1.60.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55ccb7db5a665079d68b5c7c86359ebd5ebf31a19bc1a91c982fd622f1e31ff2"}, - {file = "grpcio-1.60.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9b54577032d4f235452f77a83169b6527bf4b77d73aeada97d45b2aaf1bf5ce0"}, - {file = "grpcio-1.60.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7d142bcd604166417929b071cd396aa13c565749a4c840d6c702727a59d835eb"}, - {file = "grpcio-1.60.1-cp310-cp310-win32.whl", hash = "sha256:2a6087f234cb570008a6041c8ffd1b7d657b397fdd6d26e83d72283dae3527b1"}, - {file = "grpcio-1.60.1-cp310-cp310-win_amd64.whl", hash = "sha256:f2212796593ad1d0235068c79836861f2201fc7137a99aa2fea7beeb3b101177"}, - {file = "grpcio-1.60.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:79ae0dc785504cb1e1788758c588c711f4e4a0195d70dff53db203c95a0bd303"}, - {file = "grpcio-1.60.1-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:4eec8b8c1c2c9b7125508ff7c89d5701bf933c99d3910e446ed531cd16ad5d87"}, - {file = "grpcio-1.60.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:8c9554ca8e26241dabe7951aa1fa03a1ba0856688ecd7e7bdbdd286ebc272e4c"}, - {file = "grpcio-1.60.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91422ba785a8e7a18725b1dc40fbd88f08a5bb4c7f1b3e8739cab24b04fa8a03"}, - {file = "grpcio-1.60.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cba6209c96828711cb7c8fcb45ecef8c8859238baf15119daa1bef0f6c84bfe7"}, - {file = "grpcio-1.60.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c71be3f86d67d8d1311c6076a4ba3b75ba5703c0b856b4e691c9097f9b1e8bd2"}, - {file = "grpcio-1.60.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:af5ef6cfaf0d023c00002ba25d0751e5995fa0e4c9eec6cd263c30352662cbce"}, - {file = "grpcio-1.60.1-cp311-cp311-win32.whl", hash = "sha256:a09506eb48fa5493c58f946c46754ef22f3ec0df64f2b5149373ff31fb67f3dd"}, - {file = "grpcio-1.60.1-cp311-cp311-win_amd64.whl", hash = "sha256:49c9b6a510e3ed8df5f6f4f3c34d7fbf2d2cae048ee90a45cd7415abab72912c"}, - {file = "grpcio-1.60.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:b58b855d0071575ea9c7bc0d84a06d2edfbfccec52e9657864386381a7ce1ae9"}, - {file = "grpcio-1.60.1-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:a731ac5cffc34dac62053e0da90f0c0b8560396a19f69d9703e88240c8f05858"}, - {file = "grpcio-1.60.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:cf77f8cf2a651fbd869fbdcb4a1931464189cd210abc4cfad357f1cacc8642a6"}, - {file = "grpcio-1.60.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c557e94e91a983e5b1e9c60076a8fd79fea1e7e06848eb2e48d0ccfb30f6e073"}, - {file = "grpcio-1.60.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:069fe2aeee02dfd2135d562d0663fe70fbb69d5eed6eb3389042a7e963b54de8"}, - {file = "grpcio-1.60.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cb0af13433dbbd1c806e671d81ec75bd324af6ef75171fd7815ca3074fe32bfe"}, - {file = "grpcio-1.60.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2f44c32aef186bbba254129cea1df08a20be414144ac3bdf0e84b24e3f3b2e05"}, - {file = "grpcio-1.60.1-cp312-cp312-win32.whl", hash = "sha256:a212e5dea1a4182e40cd3e4067ee46be9d10418092ce3627475e995cca95de21"}, - {file = "grpcio-1.60.1-cp312-cp312-win_amd64.whl", hash = "sha256:6e490fa5f7f5326222cb9f0b78f207a2b218a14edf39602e083d5f617354306f"}, - {file = "grpcio-1.60.1-cp37-cp37m-linux_armv7l.whl", hash = "sha256:4216e67ad9a4769117433814956031cb300f85edc855252a645a9a724b3b6594"}, - {file = "grpcio-1.60.1-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:73e14acd3d4247169955fae8fb103a2b900cfad21d0c35f0dcd0fdd54cd60367"}, - {file = "grpcio-1.60.1-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:6ecf21d20d02d1733e9c820fb5c114c749d888704a7ec824b545c12e78734d1c"}, - {file = "grpcio-1.60.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33bdea30dcfd4f87b045d404388469eb48a48c33a6195a043d116ed1b9a0196c"}, - {file = "grpcio-1.60.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53b69e79d00f78c81eecfb38f4516080dc7f36a198b6b37b928f1c13b3c063e9"}, - {file = "grpcio-1.60.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:39aa848794b887120b1d35b1b994e445cc028ff602ef267f87c38122c1add50d"}, - {file = "grpcio-1.60.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:72153a0d2e425f45b884540a61c6639436ddafa1829a42056aa5764b84108b8e"}, - {file = "grpcio-1.60.1-cp37-cp37m-win_amd64.whl", hash = "sha256:50d56280b482875d1f9128ce596e59031a226a8b84bec88cb2bf76c289f5d0de"}, - {file = "grpcio-1.60.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:6d140bdeb26cad8b93c1455fa00573c05592793c32053d6e0016ce05ba267549"}, - {file = "grpcio-1.60.1-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:bc808924470643b82b14fe121923c30ec211d8c693e747eba8a7414bc4351a23"}, - {file = "grpcio-1.60.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:70c83bb530572917be20c21f3b6be92cd86b9aecb44b0c18b1d3b2cc3ae47df0"}, - {file = "grpcio-1.60.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9b106bc52e7f28170e624ba61cc7dc6829566e535a6ec68528f8e1afbed1c41f"}, - {file = "grpcio-1.60.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30e980cd6db1088c144b92fe376747328d5554bc7960ce583ec7b7d81cd47287"}, - {file = "grpcio-1.60.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0c5807e9152eff15f1d48f6b9ad3749196f79a4a050469d99eecb679be592acc"}, - {file = "grpcio-1.60.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f1c3dc536b3ee124e8b24feb7533e5c70b9f2ef833e3b2e5513b2897fd46763a"}, - {file = "grpcio-1.60.1-cp38-cp38-win32.whl", hash = "sha256:d7404cebcdb11bb5bd40bf94131faf7e9a7c10a6c60358580fe83913f360f929"}, - {file = "grpcio-1.60.1-cp38-cp38-win_amd64.whl", hash = "sha256:c8754c75f55781515a3005063d9a05878b2cfb3cb7e41d5401ad0cf19de14872"}, - {file = "grpcio-1.60.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:0250a7a70b14000fa311de04b169cc7480be6c1a769b190769d347939d3232a8"}, - {file = "grpcio-1.60.1-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:660fc6b9c2a9ea3bb2a7e64ba878c98339abaf1811edca904ac85e9e662f1d73"}, - {file = "grpcio-1.60.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:76eaaba891083fcbe167aa0f03363311a9f12da975b025d30e94b93ac7a765fc"}, - {file = "grpcio-1.60.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d97c65ea7e097056f3d1ead77040ebc236feaf7f71489383d20f3b4c28412a"}, - {file = "grpcio-1.60.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb2a2911b028f01c8c64d126f6b632fcd8a9ac975aa1b3855766c94e4107180"}, - {file = "grpcio-1.60.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:5a1ebbae7e2214f51b1f23b57bf98eeed2cf1ba84e4d523c48c36d5b2f8829ff"}, - {file = "grpcio-1.60.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a66f4d2a005bc78e61d805ed95dedfcb35efa84b7bba0403c6d60d13a3de2d6"}, - {file = "grpcio-1.60.1-cp39-cp39-win32.whl", hash = "sha256:8d488fbdbf04283f0d20742b64968d44825617aa6717b07c006168ed16488804"}, - {file = "grpcio-1.60.1-cp39-cp39-win_amd64.whl", hash = "sha256:61b7199cd2a55e62e45bfb629a35b71fc2c0cb88f686a047f25b1112d3810904"}, - {file = "grpcio-1.60.1.tar.gz", hash = "sha256:dd1d3a8d1d2e50ad9b59e10aa7f07c7d1be2b367f3f2d33c5fade96ed5460962"}, + {file = "grpcio-1.62.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:136ffd79791b1eddda8d827b607a6285474ff8a1a5735c4947b58c481e5e4271"}, + {file = "grpcio-1.62.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:d6a56ba703be6b6267bf19423d888600c3f574ac7c2cc5e6220af90662a4d6b0"}, + {file = "grpcio-1.62.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:4cd356211579043fce9f52acc861e519316fff93980a212c8109cca8f47366b6"}, + {file = "grpcio-1.62.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e803e9b58d8f9b4ff0ea991611a8d51b31c68d2e24572cd1fe85e99e8cc1b4f8"}, + {file = "grpcio-1.62.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4c04fe33039b35b97c02d2901a164bbbb2f21fb9c4e2a45a959f0b044c3512c"}, + {file = "grpcio-1.62.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:95370c71b8c9062f9ea033a0867c4c73d6f0ff35113ebd2618171ec1f1e903e0"}, + {file = "grpcio-1.62.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c912688acc05e4ff012c8891803659d6a8a8b5106f0f66e0aed3fb7e77898fa6"}, + {file = "grpcio-1.62.0-cp310-cp310-win32.whl", hash = "sha256:821a44bd63d0f04e33cf4ddf33c14cae176346486b0df08b41a6132b976de5fc"}, + {file = "grpcio-1.62.0-cp310-cp310-win_amd64.whl", hash = "sha256:81531632f93fece32b2762247c4c169021177e58e725494f9a746ca62c83acaa"}, + {file = "grpcio-1.62.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:3fa15850a6aba230eed06b236287c50d65a98f05054a0f01ccedf8e1cc89d57f"}, + {file = "grpcio-1.62.0-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:36df33080cd7897623feff57831eb83c98b84640b016ce443305977fac7566fb"}, + {file = "grpcio-1.62.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:7a195531828b46ea9c4623c47e1dc45650fc7206f8a71825898dd4c9004b0928"}, + {file = "grpcio-1.62.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab140a3542bbcea37162bdfc12ce0d47a3cda3f2d91b752a124cc9fe6776a9e2"}, + {file = "grpcio-1.62.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f9d6c3223914abb51ac564dc9c3782d23ca445d2864321b9059d62d47144021"}, + {file = "grpcio-1.62.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fbe0c20ce9a1cff75cfb828b21f08d0a1ca527b67f2443174af6626798a754a4"}, + {file = "grpcio-1.62.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:38f69de9c28c1e7a8fd24e4af4264726637b72f27c2099eaea6e513e7142b47e"}, + {file = "grpcio-1.62.0-cp311-cp311-win32.whl", hash = "sha256:ce1aafdf8d3f58cb67664f42a617af0e34555fe955450d42c19e4a6ad41c84bd"}, + {file = "grpcio-1.62.0-cp311-cp311-win_amd64.whl", hash = "sha256:eef1d16ac26c5325e7d39f5452ea98d6988c700c427c52cbc7ce3201e6d93334"}, + {file = "grpcio-1.62.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8aab8f90b2a41208c0a071ec39a6e5dbba16fd827455aaa070fec241624ccef8"}, + {file = "grpcio-1.62.0-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:62aa1659d8b6aad7329ede5d5b077e3d71bf488d85795db517118c390358d5f6"}, + {file = "grpcio-1.62.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:0d7ae7fc7dbbf2d78d6323641ded767d9ec6d121aaf931ec4a5c50797b886532"}, + {file = "grpcio-1.62.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f359d635ee9428f0294bea062bb60c478a8ddc44b0b6f8e1f42997e5dc12e2ee"}, + {file = "grpcio-1.62.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d48e5b1f8f4204889f1acf30bb57c30378e17c8d20df5acbe8029e985f735c"}, + {file = "grpcio-1.62.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:662d3df5314ecde3184cf87ddd2c3a66095b3acbb2d57a8cada571747af03873"}, + {file = "grpcio-1.62.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:92cdb616be44c8ac23a57cce0243af0137a10aa82234f23cd46e69e115071388"}, + {file = "grpcio-1.62.0-cp312-cp312-win32.whl", hash = "sha256:0b9179478b09ee22f4a36b40ca87ad43376acdccc816ce7c2193a9061bf35701"}, + {file = "grpcio-1.62.0-cp312-cp312-win_amd64.whl", hash = "sha256:614c3ed234208e76991992342bab725f379cc81c7dd5035ee1de2f7e3f7a9842"}, + {file = "grpcio-1.62.0-cp37-cp37m-linux_armv7l.whl", hash = "sha256:7e1f51e2a460b7394670fdb615e26d31d3260015154ea4f1501a45047abe06c9"}, + {file = "grpcio-1.62.0-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:bcff647e7fe25495e7719f779cc219bbb90b9e79fbd1ce5bda6aae2567f469f2"}, + {file = "grpcio-1.62.0-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:56ca7ba0b51ed0de1646f1735154143dcbdf9ec2dbe8cc6645def299bb527ca1"}, + {file = "grpcio-1.62.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e84bfb2a734e4a234b116be208d6f0214e68dcf7804306f97962f93c22a1839"}, + {file = "grpcio-1.62.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c1488b31a521fbba50ae86423f5306668d6f3a46d124f7819c603979fc538c4"}, + {file = "grpcio-1.62.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:98d8f4eb91f1ce0735bf0b67c3b2a4fea68b52b2fd13dc4318583181f9219b4b"}, + {file = "grpcio-1.62.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b3d3d755cfa331d6090e13aac276d4a3fb828bf935449dc16c3d554bf366136b"}, + {file = "grpcio-1.62.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a33f2bfd8a58a02aab93f94f6c61279be0f48f99fcca20ebaee67576cd57307b"}, + {file = "grpcio-1.62.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:5e709f7c8028ce0443bddc290fb9c967c1e0e9159ef7a030e8c21cac1feabd35"}, + {file = "grpcio-1.62.0-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:2f3d9a4d0abb57e5f49ed5039d3ed375826c2635751ab89dcc25932ff683bbb6"}, + {file = "grpcio-1.62.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:62ccb92f594d3d9fcd00064b149a0187c246b11e46ff1b7935191f169227f04c"}, + {file = "grpcio-1.62.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:921148f57c2e4b076af59a815467d399b7447f6e0ee10ef6d2601eb1e9c7f402"}, + {file = "grpcio-1.62.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f897b16190b46bc4d4aaf0a32a4b819d559a37a756d7c6b571e9562c360eed72"}, + {file = "grpcio-1.62.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1bc8449084fe395575ed24809752e1dc4592bb70900a03ca42bf236ed5bf008f"}, + {file = "grpcio-1.62.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81d444e5e182be4c7856cd33a610154fe9ea1726bd071d07e7ba13fafd202e38"}, + {file = "grpcio-1.62.0-cp38-cp38-win32.whl", hash = "sha256:88f41f33da3840b4a9bbec68079096d4caf629e2c6ed3a72112159d570d98ebe"}, + {file = "grpcio-1.62.0-cp38-cp38-win_amd64.whl", hash = "sha256:fc2836cb829895ee190813446dce63df67e6ed7b9bf76060262c55fcd097d270"}, + {file = "grpcio-1.62.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:fcc98cff4084467839d0a20d16abc2a76005f3d1b38062464d088c07f500d170"}, + {file = "grpcio-1.62.0-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:0d3dee701e48ee76b7d6fbbba18ba8bc142e5b231ef7d3d97065204702224e0e"}, + {file = "grpcio-1.62.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:b7a6be562dd18e5d5bec146ae9537f20ae1253beb971c0164f1e8a2f5a27e829"}, + {file = "grpcio-1.62.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29cb592c4ce64a023712875368bcae13938c7f03e99f080407e20ffe0a9aa33b"}, + {file = "grpcio-1.62.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eda79574aec8ec4d00768dcb07daba60ed08ef32583b62b90bbf274b3c279f7"}, + {file = "grpcio-1.62.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7eea57444a354ee217fda23f4b479a4cdfea35fb918ca0d8a0e73c271e52c09c"}, + {file = "grpcio-1.62.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0e97f37a3b7c89f9125b92d22e9c8323f4e76e7993ba7049b9f4ccbe8bae958a"}, + {file = "grpcio-1.62.0-cp39-cp39-win32.whl", hash = "sha256:39cd45bd82a2e510e591ca2ddbe22352e8413378852ae814549c162cf3992a93"}, + {file = "grpcio-1.62.0-cp39-cp39-win_amd64.whl", hash = "sha256:b71c65427bf0ec6a8b48c68c17356cb9fbfc96b1130d20a07cb462f4e4dcdcd5"}, + {file = "grpcio-1.62.0.tar.gz", hash = "sha256:748496af9238ac78dcd98cce65421f1adce28c3979393e3609683fcd7f3880d7"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.60.1)"] +protobuf = ["grpcio-tools (>=1.62.0)"] [[package]] name = "grpcio-tools" -version = "1.60.1" +version = "1.62.0" description = "Protobuf code generator for gRPC" optional = false python-versions = ">=3.7" files = [ - {file = "grpcio-tools-1.60.1.tar.gz", hash = "sha256:da08224ab8675c6d464b988bd8ca02cccd2bf0275bceefe8f6219bfd4a4f5e85"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:184b27333b627a7cc0972fb70d21a8bb7c02ac4a6febc16768d78ea8ff883ddd"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:18d7737f29ef5bbe3352547d0eccd080807834f00df223867dfc860bf81e9180"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:cc8ba358d2c658c6ecbc58e779bf0fc5a673fecac015a70db27fc5b4d37b76b6"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2973f75e8ba5c551033a1d59cc97654f6f386deaf2559082011d245d7ed87bba"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28ae665113affebdd109247386786e5ab4dccfcfad1b5f68e9cce2e326b57ee6"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5c7ed086fef5ff59f46d53a052b1934b73e0f7d12365d656d6af3a88057d5a3e"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8540f6480428a52614db71dd6394f52cbc0d2565b5ea1136a982f26390a42c7a"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-win32.whl", hash = "sha256:5b4a939097005531edec331f22d0b82bff26e71ede009354d2f375b5d41e74f0"}, - {file = "grpcio_tools-1.60.1-cp310-cp310-win_amd64.whl", hash = "sha256:075bb67895970f96aabc1761ca674bf4db193f8fcad387f08e50402023b5f953"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:284749d20fb22418f17d3d351b9eb838caf4a0393a9cb02c36e5c32fa4bbe9db"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:b1041377cf32ee2338284ee26e6b9c10f9ea7728092376b19803dcb9b91d510d"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:e529cd3d4109a6f4a3f7bdaca68946eb33734e2d7ffe861785a0586abe99ee67"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31294b534f25f02ead204e58dcbe0e5437a95a1a6f276bb9378905595b02ff6d"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fb6f4d2df0388c35c2804ba170f511238a681b679ead013bfe5e39d0ea9cf48"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:40cd8268a675269ce59c4fa50877597ec638bb1099c52237bb726c8ac9791868"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:985ac476da365267a2367ab20060f9096fbfc2e190fb02dd394f9ec05edf03ca"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-win32.whl", hash = "sha256:bd85f6c368b93ae45edf8568473053cb1cc075ef3489efb18f9832d4ecce062f"}, - {file = "grpcio_tools-1.60.1-cp311-cp311-win_amd64.whl", hash = "sha256:c20e752ff5057758845f4e5c7a298739bfba291f373ed18ea9c7c7acbe69e8ab"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:aafc94616c5f89c891d859057b194a153c451f9921053454e9d7d4cbf79047eb"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:9bba347000f57dae8aea79c0d76ef7d72895597524d30d0170c7d1974a3a03f3"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:1e96a532d38411f0543fe1903ff522f7142a9901afb0ed94de58d79caf1905be"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ea6e397d87f458bb2c387a4a6e1b65df74ce5b5194a1f16850c38309012e981"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aeecd5b8faa2aab67e6c8b8a57e888c00ce70d39f331ede0a21312e92def1a6"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:d2c26ce5f774c98bd2d3d8d1703048394018b55d297ebdb41ed2ba35b9a34f68"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:214281cdafb7acfdcde848eca2de7c888a6e2b5cd25ab579712b965ea09a9cd4"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-win32.whl", hash = "sha256:8c4b917aa4fcdc77990773063f0f14540aab8d4a8bf6c862b964a45d891a31d2"}, - {file = "grpcio_tools-1.60.1-cp312-cp312-win_amd64.whl", hash = "sha256:0aa34c7c21cff2177a4096b2b0d51dfbc9f8a41f929847a434e89b352c5a215d"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-linux_armv7l.whl", hash = "sha256:acdba77584981fe799104aa545d9d97910bcf88c69b668b768c1f3e7d7e5afac"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:2a7fa55bc62d4b8ebe6fb26f8cf89df3cf3b504eb6c5f3a2f0174689d35fddb0"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:dffa326cf901fe08a0e218d9fdf593f12276088a8caa07fcbec7d051149cf9ef"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf945bd22f396c0d0c691e0990db2bfc4e77816b1edc2aea8a69c35ae721aac9"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6801cfc5a85f0fb6fd12cade45942aaa1c814422328d594d12d364815fe34123"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f95bdc6c7c50b7fc442e53537bc5b4eb8cab2a671c1da80d40b5a4ab1fd5d416"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:402efeec36d8b12b792bae8a900085416fc2f57a34b599445ace2e847b6b0d75"}, - {file = "grpcio_tools-1.60.1-cp37-cp37m-win_amd64.whl", hash = "sha256:af88a2062b9c35034a80b25f289034b9c3c00c42bb88efaa465503a06fbd6a87"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:46b495bae31c5d3f6ac0240eb848f0642b5410f80dff2aacdea20cdea3938c1d"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:b5ae375207af9aa82f516dcd513d2e0c83690b7788d45844daad846ed87550f8"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:15f13e8f3d77b96adcb1e3615acec5b100bd836c6010c58a51465bcb9c06d128"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c354505e6a3d170da374f20404ea6a78135502df4f5534e5c532bdf24c4cc2a5"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8cfab27ba2bd36a3e3b522aed686133531e8b919703d0247a0885dae8815317"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b6ef213cb0aecb2832ee82a2eac32f29f31f50b17ce020604d82205096a6bd0c"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b62cb2d43a7f0eacc6a6962dfff7c2564874012e1a72ae4167e762f449e2912"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-win32.whl", hash = "sha256:3fcabf484720a9fa1690e2825fc940027a05a0c79a1075a730008ef634bd8ad2"}, - {file = "grpcio_tools-1.60.1-cp38-cp38-win_amd64.whl", hash = "sha256:22ce3e3d861321d208d8bfd6161ab976623520b179712c90b2c175151463a6b1"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:4e66fe204da15e08e599adb3060109a42927c0868fe8933e2d341ea649eceb03"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:c1047bd831de5d9da761e9dc246988d5f07d722186938dfd5f34807398101010"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:eba5fafd70585fbd4cb6ae45e3c5e11d8598e2426c9f289b78f682c0606e81cb"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bba7230c60238c7a4ffa29f1aff6d78edb41f2c79cbe4443406472b1c80ccb5d"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2bb8efc2cd64bd8f2779b426dd7e94e60924078ba5150cbbb60a846e62d1ed2"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:26f91161a91f1601777751230eaaafdf416fed08a15c3ba2ae391088e4a906c6"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2c19be2bba5583e30f88bb5d71b430176c396f0d6d0db3785e5845bfa3d28cd2"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-win32.whl", hash = "sha256:9aadc9c00baa2064baa4414cff7c269455449f14805a355226674d89c507342c"}, - {file = "grpcio_tools-1.60.1-cp39-cp39-win_amd64.whl", hash = "sha256:652b08c9fef39186ce4f97f05f5440c0ed41f117db0f7d6cb0e0d75dbc6afd3f"}, + {file = "grpcio-tools-1.62.0.tar.gz", hash = "sha256:7fca6ecfbbf0549058bb29dcc6e435d885b878d07701e77ac58e1e1f591736dc"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:465c51ebaa184ee3bb619cd5bfaf562bbdde166f2822a6935461e6a741f5ac19"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:0d9c9a4832f52c4597d6dc12d9ab3109c3bd0ee1686b8bf6d64f9eab4145e3cb"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:5a482d9625209023481e631c29a6df1392bfc49f9accfa880dabbacff642559a"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74196beed18383d53ff3e2412a6c1eefa3ff109e987be240368496bc3dcabc8b"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75aca28cbeb605c59b5689a7e000fbc2bd659d2f322c58461f3912f00069f6da"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:523adf731fa4c5af0bf7ee2edb65e8c7ef4d9df9951461d6a18fe096688efd2d"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:791aa220f8f1936e65bc079e9eb954fa0202a1f16e28b83956e59d17dface127"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-win32.whl", hash = "sha256:5dacc691b18d2c294ea971720ff980a1e2d68a3f7ddcd2f0670b3204e81c4b18"}, + {file = "grpcio_tools-1.62.0-cp310-cp310-win_amd64.whl", hash = "sha256:6999a4e705b03aacad46e625feb7610e47ec88dbd51220c2282b6334f90721fc"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:19b74e141937c885c9e56b6a7dfa190ca7d583bd48bce9171dd65bbf108b9271"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:17c16e9a89c0b9f4ff2b143f232c5256383453ce7b55fe981598f9517adc8252"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:3730b1cd998a0cffc817602cc55e51f268fa97b3e38fa4bee578e3741474547a"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14201950513636f515dd455a06890e3a21d115b943cf6a8f5af67ad1413cfa1f"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f74e0053360e0eadd75193c0c379b6d7f51d074ebbff856bd41780e1a028b38d"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d5959e3df126931d28cd94dd5f0a708b7dd96019de80ab715fb922fd0c8a838d"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1927934dfba4658a97c2dab267e53ed239264d40fdd5b295fc317693543db85b"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-win32.whl", hash = "sha256:2f5bd22203e64e1732e149bfdd3083716d038abca294e4e2852159b3d893f9ec"}, + {file = "grpcio_tools-1.62.0-cp311-cp311-win_amd64.whl", hash = "sha256:cd1f4caeca614b04db803566473f7db0971e7a88268f95e4a529b0ace699b949"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:f0884eaf6a2bbd7b03fea456e808909ee48dd4f7f455519d67defda791116368"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:6b900ae319b6f9ac1be0ca572dfb41c23a7ff6fcbf36e3be6d3054e1e4c60de6"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:3bbe79b134dfb7c98cf60e4962e31039bef824834cc7034bdf1886a2ed1097f9"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:77196c7ac8741d4a2aebb023bcc2964ac65ca44180fd791640889ab2afed3e47"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b65288ebe12e38dd3650fea65d82fcce0d35df1ae4a770b525c10119ee71962f"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:52b216c458458f6c292e12428916e80974c5113abc505a61e7b0b9f8932a785d"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88aa62303278aec45bbb26bf679269c7890346c37140ae30e39da1070c341e11"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-win32.whl", hash = "sha256:bb6802d63e42734d2baf02e1343377fe18590ed6a1f5ffbdebbbe0f8331f176b"}, + {file = "grpcio_tools-1.62.0-cp312-cp312-win_amd64.whl", hash = "sha256:d5652d3a52a2e8e1d9bdf28fbd15e21b166e31b968cd7c8c604bf31611c0bb5b"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-linux_armv7l.whl", hash = "sha256:84e27206bd884be83a7fdcef8be3c90eb1591341c0ba9b0d25ec9db1043ba2f2"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:5eb63d9207b02a0fa30216907e1e7705cc2670f933e77236c6e0eb966ad3b4bf"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:95e49839d49e79187c43cd63af5c206dc5743a01d7d3d2f039772fa743cbb30c"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ae5cd2f89e33a529790bf8aa59a459484edb05e4f58d4cf78836b9dfa1fab43"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e1fd7301d762bf5984b7e7fb62fce82cff864d75f0a57e15cfd07ae1bd79133"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e38d5800151e6804d500e329f7ddfb615c50eee0c1607593e3147a4b21037e40"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:563a75924109e75809b2919e68d7e6ae7872e63d20258aae7899b14f6ff9e18b"}, + {file = "grpcio_tools-1.62.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5f8934715577c9cc0c792b8a77f7d0dd2bb60e951161b10c5f46b60856673240"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:ed6cf7ff4a10c46f85340f9c68982f9efb29f51ee4b66828310fcdf3c2d7ffd1"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:1faa5006fe9e7b9e65c47bc23f7cd333fdcdd4ba35d44080303848266db5ab05"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:3b526dc5566161a3a17599753838b9cfbdd4cb15b6ad419aae8a5d12053fa8ae"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09db3688efd3499ce3c0b02c0bac0656abdab4cb99716f81ad879c08b92c56e"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:006ea0cc16e8bf8f307326e0556e1384f24abb402cc4e6a720aa1dfe8f268647"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b46ba0b6552b4375ede65e0c89491af532635347f78d52a72f8a027529e713ed"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ec6f561c86fe13cff3be16f297cc05e1aa1274294524743a4cf91d971866fbb0"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-win32.whl", hash = "sha256:c85391e06620d6e16a56341caae5007d0c6219beba065e1e288f2523fba6a335"}, + {file = "grpcio_tools-1.62.0-cp38-cp38-win_amd64.whl", hash = "sha256:679cf2507090e010da73e5001665c76de2a5927b2e2110e459222b1c81cb10c2"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:0e87f105f1d152934759f8975ed002d5ce057b3cdf1cc6cb63fe6008671a27b9"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:bf9f281f528e0220558d57e09b4518dec148dcb250d78bd9cbb27e09edabb3f9"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:711314cb4c6c8b3d51bafaee380ffa5012bd0567ed68f1b0b1fc07492b27acab"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54bb570bd963905de3bda596b35e06026552705edebbb2cb737b57aa5252b9e5"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dce5f04676cf94e6e2d13d7f91ac2de79097d86675bc4d404a3c24dcc0332c88"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:98ddf871c614cc0ed331c7159ebbbf5040be562279677d3bb97c2e6083539f72"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f3aaf3b20c0f7063856b2432335af8f76cf580f898e04085548cde28332d6833"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-win32.whl", hash = "sha256:3dee3be61d9032f777a9b4e2696ea3d0748a582cb99c672b5d41ca66821e8c87"}, + {file = "grpcio_tools-1.62.0-cp39-cp39-win_amd64.whl", hash = "sha256:f54b5181784464bd3573ae7dbcf053da18a4b7a75fe19960791f383be3d035ca"}, ] [package.dependencies] -grpcio = ">=1.60.1" +grpcio = ">=1.62.0" protobuf = ">=4.21.6,<5.0dev" setuptools = "*" @@ -1395,13 +1395,13 @@ test = ["eth-utils (>=1.0.1,<3)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>= [[package]] name = "identify" -version = "2.5.34" +version = "2.5.35" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.34-py2.py3-none-any.whl", hash = "sha256:a4316013779e433d08b96e5eabb7f641e6c7942e4ab5d4c509ebd2e7a8994aed"}, - {file = "identify-2.5.34.tar.gz", hash = "sha256:ee17bc9d499899bc9eaec1ac7bf2dc9eedd480db9d88b96d123d3b64a9d34f5d"}, + {file = "identify-2.5.35-py2.py3-none-any.whl", hash = "sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e"}, + {file = "identify-2.5.35.tar.gz", hash = "sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791"}, ] [package.extras] @@ -1785,13 +1785,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.6.1" +version = "3.6.2" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" files = [ - {file = "pre_commit-3.6.1-py2.py3-none-any.whl", hash = "sha256:9fe989afcf095d2c4796ce7c553cf28d4d4a9b9346de3cda079bcf40748454a4"}, - {file = "pre_commit-3.6.1.tar.gz", hash = "sha256:c90961d8aa706f75d60935aba09469a6b0bcb8345f127c3fbee4bdc5f114cf4b"}, + {file = "pre_commit-3.6.2-py2.py3-none-any.whl", hash = "sha256:ba637c2d7a670c10daedc059f5c49b5bd0aadbccfcd7ec15592cf9665117532c"}, + {file = "pre_commit-3.6.2.tar.gz", hash = "sha256:c3ef34f463045c88658c5b99f38c1e297abdcc0ff13f98d3370055fbbfabc67e"}, ] [package.dependencies] @@ -1803,22 +1803,22 @@ virtualenv = ">=20.10.0" [[package]] name = "protobuf" -version = "4.25.2" +version = "4.25.3" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "protobuf-4.25.2-cp310-abi3-win32.whl", hash = "sha256:b50c949608682b12efb0b2717f53256f03636af5f60ac0c1d900df6213910fd6"}, - {file = "protobuf-4.25.2-cp310-abi3-win_amd64.whl", hash = "sha256:8f62574857ee1de9f770baf04dde4165e30b15ad97ba03ceac65f760ff018ac9"}, - {file = "protobuf-4.25.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:2db9f8fa64fbdcdc93767d3cf81e0f2aef176284071507e3ede160811502fd3d"}, - {file = "protobuf-4.25.2-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:10894a2885b7175d3984f2be8d9850712c57d5e7587a2410720af8be56cdaf62"}, - {file = "protobuf-4.25.2-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:fc381d1dd0516343f1440019cedf08a7405f791cd49eef4ae1ea06520bc1c020"}, - {file = "protobuf-4.25.2-cp38-cp38-win32.whl", hash = "sha256:33a1aeef4b1927431d1be780e87b641e322b88d654203a9e9d93f218ee359e61"}, - {file = "protobuf-4.25.2-cp38-cp38-win_amd64.whl", hash = "sha256:47f3de503fe7c1245f6f03bea7e8d3ec11c6c4a2ea9ef910e3221c8a15516d62"}, - {file = "protobuf-4.25.2-cp39-cp39-win32.whl", hash = "sha256:5e5c933b4c30a988b52e0b7c02641760a5ba046edc5e43d3b94a74c9fc57c1b3"}, - {file = "protobuf-4.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:d66a769b8d687df9024f2985d5137a337f957a0916cf5464d1513eee96a63ff0"}, - {file = "protobuf-4.25.2-py3-none-any.whl", hash = "sha256:a8b7a98d4ce823303145bf3c1a8bdb0f2f4642a414b196f04ad9853ed0c8f830"}, - {file = "protobuf-4.25.2.tar.gz", hash = "sha256:fe599e175cb347efc8ee524bcd4b902d11f7262c0e569ececcb89995c15f0a5e"}, + {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, + {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, + {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, + {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, + {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, + {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, + {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, + {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, + {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, ] [[package]] @@ -1912,13 +1912,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" -version = "8.0.0" +version = "8.0.2" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"}, - {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"}, + {file = "pytest-8.0.2-py3-none-any.whl", hash = "sha256:edfaaef32ce5172d5466b5127b42e0d6d35ebbe4453f0e3505d96afd93f6b096"}, + {file = "pytest-8.0.2.tar.gz", hash = "sha256:d4051d623a2e0b7e51960ba963193b09ce6daeb9759a451844a21e4ddedfc1bd"}, ] [package.dependencies] @@ -2267,110 +2267,110 @@ test = ["hypothesis (==5.19.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "rpds-py" -version = "0.17.1" +version = "0.18.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.17.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4128980a14ed805e1b91a7ed551250282a8ddf8201a4e9f8f5b7e6225f54170d"}, - {file = "rpds_py-0.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ff1dcb8e8bc2261a088821b2595ef031c91d499a0c1b031c152d43fe0a6ecec8"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d65e6b4f1443048eb7e833c2accb4fa7ee67cc7d54f31b4f0555b474758bee55"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a71169d505af63bb4d20d23a8fbd4c6ce272e7bce6cc31f617152aa784436f29"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:436474f17733c7dca0fbf096d36ae65277e8645039df12a0fa52445ca494729d"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10162fe3f5f47c37ebf6d8ff5a2368508fe22007e3077bf25b9c7d803454d921"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:720215373a280f78a1814becb1312d4e4d1077b1202a56d2b0815e95ccb99ce9"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70fcc6c2906cfa5c6a552ba7ae2ce64b6c32f437d8f3f8eea49925b278a61453"}, - {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:91e5a8200e65aaac342a791272c564dffcf1281abd635d304d6c4e6b495f29dc"}, - {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:99f567dae93e10be2daaa896e07513dd4bf9c2ecf0576e0533ac36ba3b1d5394"}, - {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24e4900a6643f87058a27320f81336d527ccfe503984528edde4bb660c8c8d59"}, - {file = "rpds_py-0.17.1-cp310-none-win32.whl", hash = "sha256:0bfb09bf41fe7c51413f563373e5f537eaa653d7adc4830399d4e9bdc199959d"}, - {file = "rpds_py-0.17.1-cp310-none-win_amd64.whl", hash = "sha256:20de7b7179e2031a04042e85dc463a93a82bc177eeba5ddd13ff746325558aa6"}, - {file = "rpds_py-0.17.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:65dcf105c1943cba45d19207ef51b8bc46d232a381e94dd38719d52d3980015b"}, - {file = "rpds_py-0.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:01f58a7306b64e0a4fe042047dd2b7d411ee82e54240284bab63e325762c1147"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:071bc28c589b86bc6351a339114fb7a029f5cddbaca34103aa573eba7b482382"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae35e8e6801c5ab071b992cb2da958eee76340e6926ec693b5ff7d6381441745"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149c5cd24f729e3567b56e1795f74577aa3126c14c11e457bec1b1c90d212e38"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e796051f2070f47230c745d0a77a91088fbee2cc0502e9b796b9c6471983718c"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e820ee1004327609b28db8307acc27f5f2e9a0b185b2064c5f23e815f248f8"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1957a2ab607f9added64478a6982742eb29f109d89d065fa44e01691a20fc20a"}, - {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8587fd64c2a91c33cdc39d0cebdaf30e79491cc029a37fcd458ba863f8815383"}, - {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4dc889a9d8a34758d0fcc9ac86adb97bab3fb7f0c4d29794357eb147536483fd"}, - {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2953937f83820376b5979318840f3ee47477d94c17b940fe31d9458d79ae7eea"}, - {file = "rpds_py-0.17.1-cp311-none-win32.whl", hash = "sha256:1bfcad3109c1e5ba3cbe2f421614e70439f72897515a96c462ea657261b96518"}, - {file = "rpds_py-0.17.1-cp311-none-win_amd64.whl", hash = "sha256:99da0a4686ada4ed0f778120a0ea8d066de1a0a92ab0d13ae68492a437db78bf"}, - {file = "rpds_py-0.17.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1dc29db3900cb1bb40353772417800f29c3d078dbc8024fd64655a04ee3c4bdf"}, - {file = "rpds_py-0.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82ada4a8ed9e82e443fcef87e22a3eed3654dd3adf6e3b3a0deb70f03e86142a"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d36b2b59e8cc6e576f8f7b671e32f2ff43153f0ad6d0201250a7c07f25d570e"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3677fcca7fb728c86a78660c7fb1b07b69b281964673f486ae72860e13f512ad"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:516fb8c77805159e97a689e2f1c80655c7658f5af601c34ffdb916605598cda2"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df3b6f45ba4515632c5064e35ca7f31d51d13d1479673185ba8f9fefbbed58b9"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a967dd6afda7715d911c25a6ba1517975acd8d1092b2f326718725461a3d33f9"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dbbb95e6fc91ea3102505d111b327004d1c4ce98d56a4a02e82cd451f9f57140"}, - {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02866e060219514940342a1f84303a1ef7a1dad0ac311792fbbe19b521b489d2"}, - {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2528ff96d09f12e638695f3a2e0c609c7b84c6df7c5ae9bfeb9252b6fa686253"}, - {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd345a13ce06e94c753dab52f8e71e5252aec1e4f8022d24d56decd31e1b9b23"}, - {file = "rpds_py-0.17.1-cp312-none-win32.whl", hash = "sha256:2a792b2e1d3038daa83fa474d559acfd6dc1e3650ee93b2662ddc17dbff20ad1"}, - {file = "rpds_py-0.17.1-cp312-none-win_amd64.whl", hash = "sha256:292f7344a3301802e7c25c53792fae7d1593cb0e50964e7bcdcc5cf533d634e3"}, - {file = "rpds_py-0.17.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:8ffe53e1d8ef2520ebcf0c9fec15bb721da59e8ef283b6ff3079613b1e30513d"}, - {file = "rpds_py-0.17.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4341bd7579611cf50e7b20bb8c2e23512a3dc79de987a1f411cb458ab670eb90"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4eb548daf4836e3b2c662033bfbfc551db58d30fd8fe660314f86bf8510b93"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b686f25377f9c006acbac63f61614416a6317133ab7fafe5de5f7dc8a06d42eb"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e21b76075c01d65d0f0f34302b5a7457d95721d5e0667aea65e5bb3ab415c25"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b86b21b348f7e5485fae740d845c65a880f5d1eda1e063bc59bef92d1f7d0c55"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f175e95a197f6a4059b50757a3dca33b32b61691bdbd22c29e8a8d21d3914cae"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1701fc54460ae2e5efc1dd6350eafd7a760f516df8dbe51d4a1c79d69472fbd4"}, - {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9051e3d2af8f55b42061603e29e744724cb5f65b128a491446cc029b3e2ea896"}, - {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:7450dbd659fed6dd41d1a7d47ed767e893ba402af8ae664c157c255ec6067fde"}, - {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5a024fa96d541fd7edaa0e9d904601c6445e95a729a2900c5aec6555fe921ed6"}, - {file = "rpds_py-0.17.1-cp38-none-win32.whl", hash = "sha256:da1ead63368c04a9bded7904757dfcae01eba0e0f9bc41d3d7f57ebf1c04015a"}, - {file = "rpds_py-0.17.1-cp38-none-win_amd64.whl", hash = "sha256:841320e1841bb53fada91c9725e766bb25009cfd4144e92298db296fb6c894fb"}, - {file = "rpds_py-0.17.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:f6c43b6f97209e370124baf2bf40bb1e8edc25311a158867eb1c3a5d449ebc7a"}, - {file = "rpds_py-0.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7d63ec01fe7c76c2dbb7e972fece45acbb8836e72682bde138e7e039906e2c"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81038ff87a4e04c22e1d81f947c6ac46f122e0c80460b9006e6517c4d842a6ec"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:810685321f4a304b2b55577c915bece4c4a06dfe38f6e62d9cc1d6ca8ee86b99"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25f071737dae674ca8937a73d0f43f5a52e92c2d178330b4c0bb6ab05586ffa6"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa5bfb13f1e89151ade0eb812f7b0d7a4d643406caaad65ce1cbabe0a66d695f"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfe07308b311a8293a0d5ef4e61411c5c20f682db6b5e73de6c7c8824272c256"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a000133a90eea274a6f28adc3084643263b1e7c1a5a66eb0a0a7a36aa757ed74"}, - {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d0e8a6434a3fbf77d11448c9c25b2f25244226cfbec1a5159947cac5b8c5fa4"}, - {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:efa767c220d94aa4ac3a6dd3aeb986e9f229eaf5bce92d8b1b3018d06bed3772"}, - {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:dbc56680ecf585a384fbd93cd42bc82668b77cb525343170a2d86dafaed2a84b"}, - {file = "rpds_py-0.17.1-cp39-none-win32.whl", hash = "sha256:270987bc22e7e5a962b1094953ae901395e8c1e1e83ad016c5cfcfff75a15a3f"}, - {file = "rpds_py-0.17.1-cp39-none-win_amd64.whl", hash = "sha256:2a7b2f2f56a16a6d62e55354dd329d929560442bd92e87397b7a9586a32e3e76"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a3264e3e858de4fc601741498215835ff324ff2482fd4e4af61b46512dd7fc83"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f2f3b28b40fddcb6c1f1f6c88c6f3769cd933fa493ceb79da45968a21dccc920"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9584f8f52010295a4a417221861df9bea4c72d9632562b6e59b3c7b87a1522b7"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c64602e8be701c6cfe42064b71c84ce62ce66ddc6422c15463fd8127db3d8066"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:060f412230d5f19fc8c8b75f315931b408d8ebf56aec33ef4168d1b9e54200b1"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9412abdf0ba70faa6e2ee6c0cc62a8defb772e78860cef419865917d86c7342"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9737bdaa0ad33d34c0efc718741abaafce62fadae72c8b251df9b0c823c63b22"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9f0e4dc0f17dcea4ab9d13ac5c666b6b5337042b4d8f27e01b70fae41dd65c57"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1db228102ab9d1ff4c64148c96320d0be7044fa28bd865a9ce628ce98da5973d"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:d8bbd8e56f3ba25a7d0cf980fc42b34028848a53a0e36c9918550e0280b9d0b6"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:be22ae34d68544df293152b7e50895ba70d2a833ad9566932d750d3625918b82"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bf046179d011e6114daf12a534d874958b039342b347348a78b7cdf0dd9d6041"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:1a746a6d49665058a5896000e8d9d2f1a6acba8a03b389c1e4c06e11e0b7f40d"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0b8bf5b8db49d8fd40f54772a1dcf262e8be0ad2ab0206b5a2ec109c176c0a4"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f7f4cb1f173385e8a39c29510dd11a78bf44e360fb75610594973f5ea141028b"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7fbd70cb8b54fe745301921b0816c08b6d917593429dfc437fd024b5ba713c58"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bdf1303df671179eaf2cb41e8515a07fc78d9d00f111eadbe3e14262f59c3d0"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad059a4bd14c45776600d223ec194e77db6c20255578bb5bcdd7c18fd169361"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3664d126d3388a887db44c2e293f87d500c4184ec43d5d14d2d2babdb4c64cad"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:698ea95a60c8b16b58be9d854c9f993c639f5c214cf9ba782eca53a8789d6b19"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:c3d2010656999b63e628a3c694f23020322b4178c450dc478558a2b6ef3cb9bb"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:938eab7323a736533f015e6069a7d53ef2dcc841e4e533b782c2bfb9fb12d84b"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1e626b365293a2142a62b9a614e1f8e331b28f3ca57b9f05ebbf4cf2a0f0bdc5"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:380e0df2e9d5d5d339803cfc6d183a5442ad7ab3c63c2a0982e8c824566c5ccc"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b760a56e080a826c2e5af09002c1a037382ed21d03134eb6294812dda268c811"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5576ee2f3a309d2bb403ec292d5958ce03953b0e57a11d224c1f134feaf8c40f"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3c3461ebb4c4f1bbc70b15d20b565759f97a5aaf13af811fcefc892e9197ba"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:637b802f3f069a64436d432117a7e58fab414b4e27a7e81049817ae94de45d8d"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffee088ea9b593cc6160518ba9bd319b5475e5f3e578e4552d63818773c6f56a"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ac732390d529d8469b831949c78085b034bff67f584559340008d0f6041a049"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:93432e747fb07fa567ad9cc7aaadd6e29710e515aabf939dfbed8046041346c6"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7b7d9ca34542099b4e185b3c2a2b2eda2e318a7dbde0b0d83357a6d4421b5296"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:0387ce69ba06e43df54e43968090f3626e231e4bc9150e4c3246947567695f68"}, - {file = "rpds_py-0.17.1.tar.gz", hash = "sha256:0210b2668f24c078307260bf88bdac9d6f1093635df5123789bfee4d8d7fc8e7"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88"}, + {file = "rpds_py-0.18.0-cp310-none-win32.whl", hash = "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337"}, + {file = "rpds_py-0.18.0-cp310-none-win_amd64.whl", hash = "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836"}, + {file = "rpds_py-0.18.0-cp311-none-win32.whl", hash = "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1"}, + {file = "rpds_py-0.18.0-cp311-none-win_amd64.whl", hash = "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7"}, + {file = "rpds_py-0.18.0-cp312-none-win32.whl", hash = "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98"}, + {file = "rpds_py-0.18.0-cp312-none-win_amd64.whl", hash = "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594"}, + {file = "rpds_py-0.18.0-cp38-none-win32.whl", hash = "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e"}, + {file = "rpds_py-0.18.0-cp38-none-win_amd64.whl", hash = "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20"}, + {file = "rpds_py-0.18.0-cp39-none-win32.whl", hash = "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7"}, + {file = "rpds_py-0.18.0-cp39-none-win_amd64.whl", hash = "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f"}, + {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"}, ] [[package]] @@ -2385,19 +2385,19 @@ files = [ [[package]] name = "setuptools" -version = "69.1.0" +version = "69.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"}, - {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"}, + {file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"}, + {file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" @@ -2445,13 +2445,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.9.0" +version = "4.10.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, - {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, + {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, + {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] [[package]] @@ -2472,13 +2472,13 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.25.0" +version = "20.25.1" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"}, - {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"}, + {file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"}, + {file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"}, ] [package.dependencies] From e365b106101106e5290cbc7c3abf7752677cf480 Mon Sep 17 00:00:00 2001 From: abel Date: Thu, 7 Mar 2024 23:54:35 -0300 Subject: [PATCH 43/44] (fix) Solved several errors in the example scripts --- .../13_MsgInstantBinaryOptionsMarketLaunch.py | 1 - .../query/23_TraderDerivativeOrders.py | 2 +- .../24_AccountAddressDerivativeOrders.py | 2 +- .../query/25_DerivativeOrdersByHashes.py | 2 +- ...et.py => 33_SubaccountPositionInMarket.py} | 0 ...34_SubaccountEffectivePositionInMarket.py} | 0 .../query/41_FeeDiscountAccountInfo.py | 34 ----------------- .../exchange/query/42_FeeDiscountSchedule.py | 19 ---------- .../exchange/query/43_BalanceMismatches.py | 19 ---------- .../query/44_BalanceWithBalanceHolds.py | 19 ---------- .../query/45_FeeDiscountTierStatistics.py | 19 ---------- .../exchange/query/46_MitoVaultInfos.py | 19 ---------- .../query/47_QueryMarketIDFromVault.py | 19 ---------- .../query/48_HistoricalTradeRecords.py | 21 ----------- .../exchange/query/49_IsOptedOutOfRewards.py | 34 ----------------- .../query/50_OptedOutOfRewardsAccounts.py | 19 ---------- .../exchange/query/51_MarketVolatility.py | 30 --------------- .../exchange/query/52_BinaryOptionsMarkets.py | 19 ---------- .../53_TraderDerivativeConditionalOrders.py | 37 ------------------- .../54_MarketAtomicExecutionFeeMultiplier.py | 21 ----------- .../1_MsgExecuteContractCompat.py} | 0 21 files changed, 3 insertions(+), 333 deletions(-) rename examples/chain_client/exchange/query/{33_SubaccountPossitionInMarket.py => 33_SubaccountPositionInMarket.py} (100%) rename examples/chain_client/exchange/query/{34_SubaccountEffectivePossitionInMarket.py => 34_SubaccountEffectivePositionInMarket.py} (100%) delete mode 100644 examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py delete mode 100644 examples/chain_client/exchange/query/42_FeeDiscountSchedule.py delete mode 100644 examples/chain_client/exchange/query/43_BalanceMismatches.py delete mode 100644 examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py delete mode 100644 examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py delete mode 100644 examples/chain_client/exchange/query/46_MitoVaultInfos.py delete mode 100644 examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py delete mode 100644 examples/chain_client/exchange/query/48_HistoricalTradeRecords.py delete mode 100644 examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py delete mode 100644 examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py delete mode 100644 examples/chain_client/exchange/query/51_MarketVolatility.py delete mode 100644 examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py delete mode 100644 examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py delete mode 100644 examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py rename examples/chain_client/{authz/4_MsgExecuteContractCompat.py => wasmx/1_MsgExecuteContractCompat.py} (100%) diff --git a/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py b/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py index a1ebde82..86e66b1a 100644 --- a/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py +++ b/examples/chain_client/exchange/13_MsgInstantBinaryOptionsMarketLaunch.py @@ -39,7 +39,6 @@ async def main() -> None: oracle_symbol="UFC-KHABIB-TKO-05/30/2023", oracle_provider="UFC", oracle_type="Provider", - quote_decimals=6, oracle_scale_factor=6, maker_fee_rate=0.0005, # 0.05% taker_fee_rate=0.0010, # 0.10% diff --git a/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py b/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py index 61e98ba1..244a61b4 100644 --- a/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py +++ b/examples/chain_client/exchange/query/23_TraderDerivativeOrders.py @@ -26,7 +26,7 @@ async def main() -> None: subaccount_id = address.get_subaccount_id(index=0) - orders = await client.fetch_chain_trader_spot_orders( + orders = await client.fetch_chain_trader_derivative_orders( market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", subaccount_id=subaccount_id, ) diff --git a/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py b/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py index 469c99fb..2ecc6e2d 100644 --- a/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py +++ b/examples/chain_client/exchange/query/24_AccountAddressDerivativeOrders.py @@ -24,7 +24,7 @@ async def main() -> None: address = pub_key.to_address() await client.fetch_account(address.to_acc_bech32()) - orders = await client.fetch_chain_account_address_spot_orders( + orders = await client.fetch_chain_account_address_derivative_orders( market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", account_address=address.to_acc_bech32(), ) diff --git a/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py b/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py index ea700e6d..825f5523 100644 --- a/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py +++ b/examples/chain_client/exchange/query/25_DerivativeOrdersByHashes.py @@ -26,7 +26,7 @@ async def main() -> None: subaccount_id = address.get_subaccount_id(index=0) - orders = await client.fetch_chain_spot_orders_by_hashes( + orders = await client.fetch_chain_derivative_orders_by_hashes( market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", subaccount_id=subaccount_id, order_hashes=["0x57a01cd26f1e2080860af3264e865d7c9c034a701e30946d01c1dc7a303cf2c1"], diff --git a/examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py b/examples/chain_client/exchange/query/33_SubaccountPositionInMarket.py similarity index 100% rename from examples/chain_client/exchange/query/33_SubaccountPossitionInMarket.py rename to examples/chain_client/exchange/query/33_SubaccountPositionInMarket.py diff --git a/examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py b/examples/chain_client/exchange/query/34_SubaccountEffectivePositionInMarket.py similarity index 100% rename from examples/chain_client/exchange/query/34_SubaccountEffectivePossitionInMarket.py rename to examples/chain_client/exchange/query/34_SubaccountEffectivePositionInMarket.py diff --git a/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py b/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py deleted file mode 100644 index 15fbb7ce..00000000 --- a/examples/chain_client/exchange/query/41_FeeDiscountAccountInfo.py +++ /dev/null @@ -1,34 +0,0 @@ -import asyncio -import os - -import dotenv - -from pyinjective import PrivateKey -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") - - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - # load account - priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - fee_discount = await client.fetch_fee_discount_account_info( - account=address.to_acc_bech32(), - ) - print(fee_discount) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py b/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py deleted file mode 100644 index a0ae96cb..00000000 --- a/examples/chain_client/exchange/query/42_FeeDiscountSchedule.py +++ /dev/null @@ -1,19 +0,0 @@ -import asyncio - -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - schedule = await client.fetch_fee_discount_schedule() - print(schedule) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/43_BalanceMismatches.py b/examples/chain_client/exchange/query/43_BalanceMismatches.py deleted file mode 100644 index c7f7ca5e..00000000 --- a/examples/chain_client/exchange/query/43_BalanceMismatches.py +++ /dev/null @@ -1,19 +0,0 @@ -import asyncio - -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - mismatches = await client.fetch_balance_mismatches(dust_factor=1) - print(mismatches) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py b/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py deleted file mode 100644 index 6587c59a..00000000 --- a/examples/chain_client/exchange/query/44_BalanceWithBalanceHolds.py +++ /dev/null @@ -1,19 +0,0 @@ -import asyncio - -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - balance = await client.fetch_balance_with_balance_holds() - print(balance) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py b/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py deleted file mode 100644 index 5671e4ce..00000000 --- a/examples/chain_client/exchange/query/45_FeeDiscountTierStatistics.py +++ /dev/null @@ -1,19 +0,0 @@ -import asyncio - -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - statistics = await client.fetch_fee_discount_tier_statistics() - print(statistics) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/46_MitoVaultInfos.py b/examples/chain_client/exchange/query/46_MitoVaultInfos.py deleted file mode 100644 index 3faa5cb9..00000000 --- a/examples/chain_client/exchange/query/46_MitoVaultInfos.py +++ /dev/null @@ -1,19 +0,0 @@ -import asyncio - -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - infos = await client.fetch_mito_vault_infos() - print(infos) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py b/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py deleted file mode 100644 index e699dbaa..00000000 --- a/examples/chain_client/exchange/query/47_QueryMarketIDFromVault.py +++ /dev/null @@ -1,19 +0,0 @@ -import asyncio - -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - market_id = await client.fetch_market_id_from_vault(vault_address="inj1qg5ega6dykkxc307y25pecuufrjkxkag6xhp6y") - print(market_id) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py b/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py deleted file mode 100644 index 6b93200f..00000000 --- a/examples/chain_client/exchange/query/48_HistoricalTradeRecords.py +++ /dev/null @@ -1,21 +0,0 @@ -import asyncio - -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - records = await client.fetch_historical_trade_records( - market_id="0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - ) - print(records) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py b/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py deleted file mode 100644 index 28c0925c..00000000 --- a/examples/chain_client/exchange/query/49_IsOptedOutOfRewards.py +++ /dev/null @@ -1,34 +0,0 @@ -import asyncio -import os - -import dotenv - -from pyinjective import PrivateKey -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") - - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - # load account - priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - is_opted_out = await client.fetch_is_opted_out_of_rewards( - account=address.to_acc_bech32(), - ) - print(is_opted_out) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py b/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py deleted file mode 100644 index 9940f799..00000000 --- a/examples/chain_client/exchange/query/50_OptedOutOfRewardsAccounts.py +++ /dev/null @@ -1,19 +0,0 @@ -import asyncio - -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - opted_out = await client.fetch_opted_out_of_rewards_accounts() - print(opted_out) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/51_MarketVolatility.py b/examples/chain_client/exchange/query/51_MarketVolatility.py deleted file mode 100644 index 3173ca39..00000000 --- a/examples/chain_client/exchange/query/51_MarketVolatility.py +++ /dev/null @@ -1,30 +0,0 @@ -import asyncio - -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - market_id = "0x0611780ba69656949525013d947713300f56c37b6175e02f26bffa495c3208fe" - trade_grouping_sec = 10 - max_age = 0 - include_raw_history = True - include_metadata = True - volatility = await client.fetch_market_volatility( - market_id=market_id, - trade_grouping_sec=trade_grouping_sec, - max_age=max_age, - include_raw_history=include_raw_history, - include_metadata=include_metadata, - ) - print(volatility) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py b/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py deleted file mode 100644 index 4448a4ec..00000000 --- a/examples/chain_client/exchange/query/52_BinaryOptionsMarkets.py +++ /dev/null @@ -1,19 +0,0 @@ -import asyncio - -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - markets = await client.fetch_chain_binary_options_markets(status="Active") - print(markets) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py b/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py deleted file mode 100644 index fd65e68f..00000000 --- a/examples/chain_client/exchange/query/53_TraderDerivativeConditionalOrders.py +++ /dev/null @@ -1,37 +0,0 @@ -import asyncio -import os - -import dotenv - -from pyinjective import PrivateKey -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - dotenv.load_dotenv() - configured_private_key = os.getenv("INJECTIVE_PRIVATE_KEY") - - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - # load account - priv_key = PrivateKey.from_hex(configured_private_key) - pub_key = priv_key.to_public_key() - address = pub_key.to_address() - await client.fetch_account(address.to_acc_bech32()) - - subaccount_id = address.get_subaccount_id(index=0) - - orders = await client.fetch_trader_derivative_conditional_orders( - subaccount_id=subaccount_id, - market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", - ) - print(orders) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py b/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py deleted file mode 100644 index 328028d3..00000000 --- a/examples/chain_client/exchange/query/54_MarketAtomicExecutionFeeMultiplier.py +++ /dev/null @@ -1,21 +0,0 @@ -import asyncio - -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - # select network: local, testnet, mainnet - network = Network.testnet() - - # initialize grpc client - client = AsyncClient(network) - - multiplier = await client.fetch_market_atomic_execution_fee_multiplier( - market_id="0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6", - ) - print(multiplier) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main()) diff --git a/examples/chain_client/authz/4_MsgExecuteContractCompat.py b/examples/chain_client/wasmx/1_MsgExecuteContractCompat.py similarity index 100% rename from examples/chain_client/authz/4_MsgExecuteContractCompat.py rename to examples/chain_client/wasmx/1_MsgExecuteContractCompat.py From ec1fb93ace9758adb6f1b6ce9097295eba86c022 Mon Sep 17 00:00:00 2001 From: abel Date: Fri, 8 Mar 2024 09:45:56 -0300 Subject: [PATCH 44/44] (fix) Updated SDK version in pyproject.toml. Updated denoms .ini files --- pyinjective/denoms_devnet.ini | 34 +++++++- pyinjective/denoms_mainnet.ini | 141 +++++++++++++++++++++++++++++++++ pyinjective/denoms_testnet.ini | 92 +++++++++++++++++++++ pyproject.toml | 2 +- 4 files changed, 264 insertions(+), 5 deletions(-) diff --git a/pyinjective/denoms_devnet.ini b/pyinjective/denoms_devnet.ini index 3c422179..2b6020db 100644 --- a/pyinjective/denoms_devnet.ini +++ b/pyinjective/denoms_devnet.ini @@ -164,10 +164,10 @@ min_display_quantity_tick_size = 0.00001 description = 'Devnet Spot PROJ/INJ' base = 18 quote = 18 -min_price_tick_size = 0.001 -min_display_price_tick_size = 0.001 -min_quantity_tick_size = 10000000000000 -min_display_quantity_tick_size = 0.00001 +min_price_tick_size = 0.00000001 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000000000000000 +min_display_quantity_tick_size = 1000 [0x2d3b8d8833dda54a717adea9119134556848105fd6028e9a4a526e4e5a122a57] description = 'Devnet Spot KIRA/INJ' @@ -178,6 +178,24 @@ min_display_price_tick_size = 0.00000001 min_quantity_tick_size = 1000000000 min_display_quantity_tick_size = 1000 +[0x42edf70cc37e155e9b9f178e04e18999bc8c404bd7b638cc4cbf41da8ef45a21] +description = 'Devnet Spot QUNT/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000 +min_display_quantity_tick_size = 1000 + +[0xc8fafa1fcab27e16da20e98b4dc9dda45320418c27db80663b21edac72f3b597] +description = 'Devnet Spot HDRO/INJ' +base = 6 +quote = 18 +min_price_tick_size = 1000000 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 1000000 +min_display_quantity_tick_size = 1 + [0x1422a13427d5eabd4d8de7907c8340f7e58cb15553a9fd4ad5c90406561886f9] description = 'Devnet Derivative COMP/USDT PERP' base = 0 @@ -296,6 +314,10 @@ decimals = 18 peggy_denom = peggy0xAaEf88cEa01475125522e117BFe45cF32044E238 decimals = 18 +[HDRO] +peggy_denom = factory/inj1etz0laas6h7vemg3qtd67jpr6lh8v7xz7gfzqw/hdro +decimals = 6 + [INJ] peggy_denom = inj decimals = 18 @@ -316,6 +338,10 @@ decimals = 18 peggy_denom = proj decimals = 18 +[QUNT] +peggy_denom = factory/inj127l5a2wmkyvucxdlupqyac3y0v6wqfhq03ka64/qunt +decimals = 6 + [SOMM] peggy_denom = ibc/34346A60A95EB030D62D6F5BDD4B745BE18E8A693372A8A347D5D53DBBB1328B decimals = 6 diff --git a/pyinjective/denoms_mainnet.ini b/pyinjective/denoms_mainnet.ini index 9d88ca6d..5f6611ef 100644 --- a/pyinjective/denoms_mainnet.ini +++ b/pyinjective/denoms_mainnet.ini @@ -682,6 +682,15 @@ min_display_price_tick_size = 0.000001 min_quantity_tick_size = 10000000000000000000 min_display_quantity_tick_size = 10 +[0xe6dd9895b169e2ca0087fcb8e8013805d06c3ed8ffc01ccaa31c710eef14a984] +description = 'Mainnet Spot DOJO/INJ' +base = 18 +quote = 18 +min_price_tick_size = 0.000001 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 10000000000000000000 +min_display_quantity_tick_size = 10 + [0x0a1366c8b05658c0ccca6064e4b20aacd5ad350c02debd6ec0f4dc9178145d14] description = 'Mainnet Spot GYEN/USDT' base = 6 @@ -700,6 +709,78 @@ min_display_price_tick_size = 0.0001 min_quantity_tick_size = 100000 min_display_quantity_tick_size = 0.1 +[0x9c42d763ba5135809ac4684b02082e9c880d69f6b96d258fe4c172396e9af7be] +description = 'Mainnet Spot ANDR/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000000 +min_display_price_tick_size = 0.00001 +min_quantity_tick_size = 100000 +min_display_quantity_tick_size = 0.1 + +[0x1b1e062b3306f26ae3af3c354a10c1cf38b00dcb42917f038ba3fc14978b1dd8] +description = 'Mainnet Spot hINJ/INJ' +base = 18 +quote = 18 +min_price_tick_size = 0.0001 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1000000000000000 +min_display_quantity_tick_size = 0.001 + +[0x959c9401a557ac090fff3ec11db5a1a9832e51a97a41b722d2496bb3cb0b2f72] +description = 'Mainnet Spot ANDR/INJ' +base = 6 +quote = 6 +min_price_tick_size = 0.0001 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1000000 +min_display_quantity_tick_size = 1 + +[0x697457537bc2af5ff652bc0616fe23537437a570d0e4d91566f03af279e095d5] +description = 'Mainnet Spot PHUC/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000 +min_display_quantity_tick_size = 1000 + +[0x42edf70cc37e155e9b9f178e04e18999bc8c404bd7b638cc4cbf41da8ef45a21] +description = 'Mainnet Spot QUNT/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000 +min_display_quantity_tick_size = 1000 + +[0x586409ac5f6d6e90a81d2585b9a8e76de0b4898d5f2c047d0bc025a036489ba1] +description = 'Mainnet Spot WHALE/INJ' +base = 6 +quote = 18 +min_price_tick_size = 1000000 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 1000000 +min_display_quantity_tick_size = 1 + +[0xc8fafa1fcab27e16da20e98b4dc9dda45320418c27db80663b21edac72f3b597] +description = 'Mainnet Spot HDRO/INJ' +base = 6 +quote = 18 +min_price_tick_size = 1000000 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 1000000 +min_display_quantity_tick_size = 1 + +[0xb965ebede42e67af153929339040e650d5c2af26d6aa43382c110d943c627b0a] +description = 'Mainnet Spot PYTH/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000000 +min_display_price_tick_size = 0.00001 +min_quantity_tick_size = 100000 +min_display_quantity_tick_size = 0.1 + [0x4ca0f92fc28be0c9761326016b5a1a2177dd6375558365116b5bdda9abc229ce] description = 'Mainnet Derivative BTC/USDT PERP' base = 0 @@ -772,6 +853,15 @@ min_display_price_tick_size = 0.01 min_quantity_tick_size = 0.001 min_display_quantity_tick_size = 0.001 +[0x3b7fb1d9351f7fa2e6e0e5a11b3639ee5e0486c33a6a74f629c3fc3c3043efd5] +description = 'Mainnet Derivative BONK/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 0.01 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 10000 +min_display_quantity_tick_size = 10000 + [0xcd0c859a99f26bb3530e21890937ed77d20754aa7825a599c71710514fc125ef] description = 'Mainnet Derivative 1MPEPE/USDT PERP' base = 0 @@ -889,10 +979,41 @@ min_display_price_tick_size = 0.001 min_quantity_tick_size = 0.1 min_display_quantity_tick_size = 0.1 +[0xf1bc70398e9b469db459f3153433c6bd1253bd02377248ee29bd346a218e6243] +description = 'Mainnet Derivative W/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 100 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1 +min_display_quantity_tick_size = 1 + +[0x03c8da1f6aaf8aca2be26b0f4d6b89d475835c7812a1dcdb19af7dec1c6b7f60] +description = 'Mainnet Derivative LINK/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.01 +min_quantity_tick_size = 0.01 +min_display_quantity_tick_size = 0.01 + +[0x7980993e508e0efc1c2634c153a1ef90f517b74351d6406221c77c04ec4799fe] +description = 'Mainnet Derivative DOGE/USDT PERP' +base = 0 +quote = 6 +min_price_tick_size = 10 +min_display_price_tick_size = 0.00001 +min_quantity_tick_size = 10 +min_display_quantity_tick_size = 10 + [AAVE] peggy_denom = peggy0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9 decimals = 18 +[ANDR] +peggy_denom = ibc/61FA42C3F0B0F8768ED2CE380EDD3BE0E4CB7E67688F81F70DE9ECF5F8684E1E +decimals = 6 + [APE] peggy_denom = peggy0x4d224452801ACEd8B2F0aebE155379bb5D594381 decimals = 18 @@ -937,6 +1058,10 @@ decimals = 8 peggy_denom = ibc/3A6DD3358D9F7ADD18CDE79BA10B400511A5DE4AE2C037D7C9639B52ADAF35C6 decimals = 6 +[DOJO] +peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj1zdj9kqnknztl2xclm5ssv25yre09f8908d4923 +decimals = 18 + [DOT] peggy_denom = ibc/624BA9DD171915A2B9EA70F69638B2CEA179959850C1A586F6C485498F29EDD4 decimals = 10 @@ -965,6 +1090,10 @@ decimals = 18 peggy_denom = peggy0xC08512927D12348F6620a698105e1BAac6EcD911 decimals = 6 +[HDRO] +peggy_denom = factory/inj1etz0laas6h7vemg3qtd67jpr6lh8v7xz7gfzqw/hdro +decimals = 6 + [HUAHUA] peggy_denom = ibc/E7807A46C0B7B44B350DA58F51F278881B863EC4DCA94635DAB39E52C30766CB decimals = 6 @@ -1021,6 +1150,10 @@ decimals = 6 peggy_denom = ibc/C20C0A822BD22B2CEF0D067400FCCFB6FAEEE9E91D360B4E0725BD522302D565 decimals = 6 +[PHUC] +peggy_denom = factory/inj1995xnrrtnmtdgjmx0g937vf28dwefhkhy6gy5e/phuc +decimals = 6 + [PUG] peggy_denom = peggy0xf9a06dE3F6639E6ee4F079095D5093644Ad85E8b decimals = 18 @@ -1033,6 +1166,10 @@ decimals = 6 peggy_denom = peggy0x4a220E6096B25EADb88358cb44068A3248254675 decimals = 18 +[QUNT] +peggy_denom = factory/inj127l5a2wmkyvucxdlupqyac3y0v6wqfhq03ka64/qunt +decimals = 6 + [SNOWY] peggy_denom = factory/inj1ml33x7lkxk6x2x95d3alw4h84evlcdz2gnehmk/SNOWY decimals = 6 @@ -1125,6 +1262,10 @@ decimals = 6 peggy_denom = peggy0xb2617246d0c6c0087f18703d576831899ca94f01 decimals = 18 +[hINJ] +peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj18luqttqyckgpddndh8hvaq25d5nfwjc78m56lc +decimals = 18 + [nINJ] peggy_denom = factory/inj14ejqjyq8um4p3xfqj74yld5waqljf88f9eneuk/inj13xlpypcwl5fuc84uhqzzqumnrcfpptyl6w3vrf decimals = 18 diff --git a/pyinjective/denoms_testnet.ini b/pyinjective/denoms_testnet.ini index fd823592..e8b5aa61 100644 --- a/pyinjective/denoms_testnet.ini +++ b/pyinjective/denoms_testnet.ini @@ -142,6 +142,24 @@ min_display_price_tick_size = 0.001 min_quantity_tick_size = 10000000000000 min_display_quantity_tick_size = 0.00001 +[0x21d4ee074f37f2a310929425e58f69850fca9f734d292bfc5ee48d3c28ea1c09] +description = 'Testnet Spot TEST2/INJ' +base = 6 +quote = 18 +min_price_tick_size = 100000000 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1000 +min_display_quantity_tick_size = 0.001 + +[0xf2ced33ef12a73962be92686503450cc4966feeb9cf6c809f4dc43acad5d7efb] +description = 'Testnet Spot TEST2/USDT' +base = 6 +quote = 6 +min_price_tick_size = 0.0001 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1000 +min_display_quantity_tick_size = 0.001 + [0xf02752c2c87728af7fd10a298a8a645261859eafd0295dcda7e2c5b45c8412cf] description = 'Testnet Spot stINJ/INJ' base = 18 @@ -205,6 +223,60 @@ min_display_price_tick_size = 0.001 min_quantity_tick_size = 100000 min_display_quantity_tick_size = 0.001 +[0xe93f09f7a06d507ff8b66f2969e1af931c9eb9ec3f640a6f87dbcd3456258466] +description = 'Testnet Spot Inj' +base = 18 +quote = 8 +min_price_tick_size = 0.0000000000001 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 1000000000000000 +min_display_quantity_tick_size = 0.001 + +[0xed865fd44f1bc9d46d978db415ed00444fac4f6aef7e09e2d0235f8d140b219f] +description = 'Testnet Spot MT/INJ' +base = 6 +quote = 18 +min_price_tick_size = 10000 +min_display_price_tick_size = 0.00000001 +min_quantity_tick_size = 1000000000 +min_display_quantity_tick_size = 1000 + +[0x215970bfdea5c94d8e964a759d3ce6eae1d113900129cc8428267db5ccdb3d1a] +description = 'Testnet Spot INJ/USDC' +base = 18 +quote = 6 +min_price_tick_size = 0.000000000000001 +min_display_price_tick_size = 0.001 +min_quantity_tick_size = 10000000000000000 +min_display_quantity_tick_size = 0.01 + +[0xd8e9ea042ac67990134d8e024a251809b1b76c5f7df49f511858e040a285efca] +description = 'Testnet Spot HDRO/INJ' +base = 6 +quote = 18 +min_price_tick_size = 1000000 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 1000000 +min_display_quantity_tick_size = 1 + +[0x2d7f47811527bd721ce2e4e0ff27b0f3a281f65abcd41758baf157c8ddfcd910] +description = 'Testnet Spot hINJ/INJ' +base = 18 +quote = 18 +min_price_tick_size = 0.0001 +min_display_price_tick_size = 0.0001 +min_quantity_tick_size = 1000000000000000 +min_display_quantity_tick_size = 0.001 + +[0xe4b31c0112c89e0963b2db6884b416c17101a899e0ce6dc9f5dde79e6a01b52b] +description = 'Testnet Spot TEST1/INJ' +base = 6 +quote = 18 +min_price_tick_size = 1000000 +min_display_price_tick_size = 0.000001 +min_quantity_tick_size = 1000000 +min_display_quantity_tick_size = 1 + [0x2e94326a421c3f66c15a3b663c7b1ab7fb6a5298b3a57759ecf07f0036793fc9] description = 'Testnet Derivative BTC/USDT PERP Pyth' base = 0 @@ -393,10 +465,18 @@ decimals = 18 peggy_denom = factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/atom decimals = 8 +[HDRO] +peggy_denom = factory/inj1pk7jhvjj2lufcghmvr7gl49dzwkk3xj0uqkwfk/hdro +decimals = 6 + [INJ] peggy_denom = inj decimals = 18 +[MT] +peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/mitotest2 +decimals = 6 + [MitoTest1] peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/mitotest1 decimals = 18 @@ -409,6 +489,14 @@ decimals = 18 peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/projx decimals = 18 +[TEST1] +peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/test1 +decimals = 6 + +[TEST2] +peggy_denom = factory/inj1gvhyp8un5l9jpxpd90rdtj3ejd6qser2s2jxtz/test2 +decimals = 6 + [USD Coin] peggy_denom = factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/usdc decimals = 6 @@ -437,6 +525,10 @@ decimals = 18 peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/uzen decimals = 18 +[hINJ] +peggy_denom = factory/inj1hdvy6tl89llqy3ze8lv6mz5qh66sx9enn0jxg6/inj1mz7mfhgx8tuvjqut03qdujrkzwlx9xhcj6yldc +decimals = 18 + [stINJ] peggy_denom = factory/inj17gkuet8f6pssxd8nycm3qr9d9y699rupv6397z/stinj decimals = 18 diff --git a/pyproject.toml b/pyproject.toml index c983dd07..85f36e5f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "injective-py" -version = "1.4.0-pre" +version = "1.4.0" description = "Injective Python SDK, with Exchange API Client" authors = ["Injective Labs "] license = "Apache-2.0"