From d79c9a7e335e4aa555bfd43f334d0acd7c4717af Mon Sep 17 00:00:00 2001 From: abel Date: Mon, 16 Oct 2023 12:11:55 -0300 Subject: [PATCH 1/6] (fix) Updated TIA future market id in mainnet ini file --- pyinjective/denoms_mainnet.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyinjective/denoms_mainnet.ini b/pyinjective/denoms_mainnet.ini index 1f3fe227..71706e68 100644 --- a/pyinjective/denoms_mainnet.ini +++ b/pyinjective/denoms_mainnet.ini @@ -565,7 +565,7 @@ min_display_price_tick_size = 0.0001 min_quantity_tick_size = 0.1 min_display_quantity_tick_size = 0.1 -[0x4b7a550e1760cbd2c6ccb97562c56878083b92e32d07e9e3326945c6e60e6b60] +[0x64c3a57b693ede854b0a2794ed5c99546925d1fbe74d91a2e3286e4155a00dee] description = 'Mainnet Derivative TIA/USDT-30NOV2023 PERP' base = 0 quote = 6 From b564a3e15df8a5ff81ce45542942cde882b866c0 Mon Sep 17 00:00:00 2001 From: abel Date: Mon, 16 Oct 2023 12:14:29 -0300 Subject: [PATCH 2/6] (fix) Updated version number and changelog --- README.md | 3 +++ pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2ad1d67d..e094c565 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,9 @@ poetry run pytest -v ``` ### Changelogs +**0.9.3** +* Updated TIA/USDT-30NOV2023 market id in denoms_mainnet.ini file + **0.9.2** * Added fix to the grpc import error in Mac with M1 and M2 chips diff --git a/pyproject.toml b/pyproject.toml index 737dbd6a..07bbadb2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "injective-py" -version = "0.9.2" +version = "0.9.3" description = "Injective Python SDK, with Exchange API Client" authors = ["Injective Labs "] license = "Apache-2.0" From 20c966b9a652cac4e7057b604cf0787cf3057b7d Mon Sep 17 00:00:00 2001 From: abel Date: Fri, 6 Oct 2023 12:53:14 -0300 Subject: [PATCH 3/6] (feat) Added example for liquidable positions request. Also removed sentry nodes from network config --- .../23_LiquidablePositions.py | 30 +++++++++++++++++++ pyinjective/core/network.py | 13 +------- 2 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 examples/exchange_client/derivative_exchange_rpc/23_LiquidablePositions.py diff --git a/examples/exchange_client/derivative_exchange_rpc/23_LiquidablePositions.py b/examples/exchange_client/derivative_exchange_rpc/23_LiquidablePositions.py new file mode 100644 index 00000000..e87f67b1 --- /dev/null +++ b/examples/exchange_client/derivative_exchange_rpc/23_LiquidablePositions.py @@ -0,0 +1,30 @@ +import asyncio + +from google.protobuf import json_format + +from pyinjective.async_client import AsyncClient +from pyinjective.core.network import Network + + +async def main() -> None: + network = Network.testnet() + client = AsyncClient(network) + market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" + skip = 10 + limit = 3 + positions = await client.get_derivative_liquidable_positions( + market_id=market_id, + skip=skip, + limit=limit, + ) + print( + json_format.MessageToJson( + message=positions, + including_default_value_fields=True, + preserving_proto_field_name=True, + ) + ) + + +if __name__ == "__main__": + asyncio.get_event_loop().run_until_complete(main()) diff --git a/pyinjective/core/network.py b/pyinjective/core/network.py index 39c4af65..9131329a 100644 --- a/pyinjective/core/network.py +++ b/pyinjective/core/network.py @@ -244,9 +244,6 @@ def mainnet(cls, node="lb"): nodes = [ "lb", # us, asia, prod "lb_k8s", - "sentry0", # ca, prod - "sentry1", # ca, prod - "sentry3", # us, prod ] if node not in nodes: raise ValueError("Must be one of {}".format(nodes)) @@ -259,7 +256,7 @@ def mainnet(cls, node="lb"): grpc_explorer_endpoint = "sentry.explorer.grpc.injective.network:443" cookie_assistant = BareMetalLoadBalancedCookieAssistant() use_secure_connection = True - elif node == "lb_k8s": + else: lcd_endpoint = "https://k8s.global.mainnet.lcd.injective.network:443" tm_websocket_endpoint = "wss://k8s.global.mainnet.tm.injective.network:443/websocket" grpc_endpoint = "k8s.global.mainnet.chain.grpc.injective.network:443" @@ -267,14 +264,6 @@ def mainnet(cls, node="lb"): grpc_explorer_endpoint = "k8s.global.mainnet.explorer.grpc.injective.network:443" cookie_assistant = KubernetesLoadBalancedCookieAssistant() use_secure_connection = True - else: - lcd_endpoint = f"http://{node}.injective.network:10337" - tm_websocket_endpoint = f"ws://{node}.injective.network:26657/websocket" - grpc_endpoint = f"{node}.injective.network:9900" - grpc_exchange_endpoint = f"{node}.injective.network:9910" - grpc_explorer_endpoint = f"{node}.injective.network:9911" - cookie_assistant = DisabledCookieAssistant() - use_secure_connection = False return cls( lcd_endpoint=lcd_endpoint, From 33e4b01194bec6eefa396185bde2fc987be61e71 Mon Sep 17 00:00:00 2001 From: abel Date: Mon, 16 Oct 2023 15:37:38 -0300 Subject: [PATCH 4/6] (feat) Remove aiocron dependency. Use pure asyncio task to update the timeout height --- .github/workflows/run-tests.yml | 2 +- README.md | 3 + poetry.lock | 104 +++----------------------------- pyinjective/async_client.py | 28 ++++++--- pyproject.toml | 3 +- 5 files changed, 32 insertions(+), 108 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index ccde1d03..95fa937f 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -8,7 +8,7 @@ jobs: run-tests: strategy: matrix: - python: ["3.9", "3.10", "3.11"] + python: ["3.9", "3.10", "3.11", "3.12"] os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} env: diff --git a/README.md b/README.md index e094c565..4d9e67ed 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,9 @@ poetry run pytest -v ``` ### Changelogs +**0.10** +* Remove `aiocron` dependency. Use plain asyncio tasks to solve the timeout height synchronization + **0.9.3** * Updated TIA/USDT-30NOV2023 market id in denoms_mainnet.ini file diff --git a/poetry.lock b/poetry.lock index 33a290a5..d4adc5dd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,23 +1,5 @@ # This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. -[[package]] -name = "aiocron" -version = "1.8" -description = "Crontabs for asyncio" -optional = false -python-versions = "*" -files = [ - {file = "aiocron-1.8-py3-none-any.whl", hash = "sha256:b6313214c311b62aa2220e872b94139b648631b3103d062ef29e5d3230ddce6d"}, - {file = "aiocron-1.8.tar.gz", hash = "sha256:48546513faf2eb7901e65a64eba7b653c80106ed00ed9ca3419c3d10b6555a01"}, -] - -[package.dependencies] -croniter = "*" -tzlocal = "*" - -[package.extras] -test = ["coverage"] - [[package]] name = "aiohttp" version = "3.8.6" @@ -742,21 +724,6 @@ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.1 [package.extras] toml = ["tomli"] -[[package]] -name = "croniter" -version = "2.0.1" -description = "croniter provides iteration for datetime object with cron like format" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "croniter-2.0.1-py2.py3-none-any.whl", hash = "sha256:4cb064ce2d8f695b3b078be36ff50115cf8ac306c10a7e8653ee2a5b534673d7"}, - {file = "croniter-2.0.1.tar.gz", hash = "sha256:d199b2ec3ea5e82988d1f72022433c5f9302b3b3ea9e6bfd6a1518f6ea5e700a"}, -] - -[package.dependencies] -python-dateutil = "*" -pytz = ">2021.1" - [[package]] name = "cytoolz" version = "0.12.2" @@ -1806,13 +1773,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.4.0" +version = "3.5.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.8" files = [ - {file = "pre_commit-3.4.0-py2.py3-none-any.whl", hash = "sha256:96d529a951f8b677f730a7212442027e8ba53f9b04d217c4c67dc56c393ad945"}, - {file = "pre_commit-3.4.0.tar.gz", hash = "sha256:6bbd5129a64cad4c0dfaeeb12cd8f7ea7e15b77028d985341478c8af3c759522"}, + {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"}, + {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"}, ] [package.dependencies] @@ -2004,31 +1971,6 @@ files = [ [package.dependencies] pytest = ">=3.6.0" -[[package]] -name = "python-dateutil" -version = "2.8.2" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "pytz" -version = "2023.3.post1" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -files = [ - {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, - {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, -] - [[package]] name = "pyunormalize" version = "15.0.0" @@ -2483,34 +2425,6 @@ files = [ {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, ] -[[package]] -name = "tzdata" -version = "2023.3" -description = "Provider of IANA time zone data" -optional = false -python-versions = ">=2" -files = [ - {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, - {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, -] - -[[package]] -name = "tzlocal" -version = "5.1" -description = "tzinfo object for the local timezone" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tzlocal-5.1-py3-none-any.whl", hash = "sha256:2938498395d5f6a898ab8009555cb37a4d360913ad375d4747ef16826b03ef23"}, - {file = "tzlocal-5.1.tar.gz", hash = "sha256:a5ccb2365b295ed964e0a98ad076fe10c495591e75505d34f154d60a7f1ed722"}, -] - -[package.dependencies] -tzdata = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -devenv = ["black", "check-manifest", "flake8", "pyroma", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] - [[package]] name = "urllib3" version = "1.26.17" @@ -2549,13 +2463,13 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "web3" -version = "6.10.0" +version = "6.11.0" description = "web3.py" optional = false python-versions = ">=3.7.2" files = [ - {file = "web3-6.10.0-py3-none-any.whl", hash = "sha256:070625a0da4f0fcac090fa95186e0b865a1bbc43efb78fd2ee805f7bf9cd8986"}, - {file = "web3-6.10.0.tar.gz", hash = "sha256:ea89f8a6ee74b74c3ff21954eafe00ec914365adb904c6c374f559bc46d4a61c"}, + {file = "web3-6.11.0-py3-none-any.whl", hash = "sha256:44e79da6a4765eacf137f2f388e37aa0c1e24a93bdfb462cffe9441d1be3d509"}, + {file = "web3-6.11.0.tar.gz", hash = "sha256:050dea52ae73d787272e7ecba7249f096595938c90cce1a384c20375c6b0f720"}, ] [package.dependencies] @@ -2576,10 +2490,10 @@ 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.0.0)", "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.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)"] 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.0.0)", "types-protobuf (==3.19.13)", "types-requests (>=2.26.1)", "types-setuptools (>=57.4.4)"] +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)"] [[package]] @@ -2751,4 +2665,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "1c74ebf70d3cc8987fe3218c68cb29aa1a11121e1bd854af44dd2886413b5541" +content-hash = "3f60f1e4f2c0c5fe4f53f91d5320395e7063c477dd50524accd5fd3f9677bcf0" diff --git a/pyinjective/async_client.py b/pyinjective/async_client.py index f279b45f..b32bbec4 100644 --- a/pyinjective/async_client.py +++ b/pyinjective/async_client.py @@ -4,7 +4,6 @@ from decimal import Decimal from typing import Coroutine, Dict, List, Optional, Tuple, Union -import aiocron import grpc from pyinjective.composer import Composer @@ -108,13 +107,8 @@ def __init__( ) self.stubExplorer = explorer_rpc_grpc.InjectiveExplorerRPCStub(self.explorer_channel) - # timeout height update routine - self.cron = aiocron.crontab( - "* * * * * */{}".format(DEFAULT_TIMEOUTHEIGHT_SYNC_INTERVAL), - func=self.sync_timeout_height, - args=(), - start=True, - ) + self._timeout_height_sync_task = None + self._initialize_timeout_height_sync_task() self._tokens_and_markets_initialization_lock = asyncio.Lock() self._tokens: Optional[Dict[str, Token]] = None @@ -163,11 +157,11 @@ async def get_tx(self, tx_hash): async def close_exchange_channel(self): await self.exchange_channel.close() - self.cron.stop() + self._cancel_timeout_height_sync_task() async def close_chain_channel(self): await self.chain_channel.close() - self.cron.stop() + self._cancel_timeout_height_sync_task() async def sync_timeout_height(self): try: @@ -1009,3 +1003,17 @@ def _chain_cookie_metadata_requestor(self) -> Coroutine: def _exchange_cookie_metadata_requestor(self) -> Coroutine: request = exchange_meta_rpc_pb.VersionRequest() return self.stubMeta.Version(request).initial_metadata() + + def _initialize_timeout_height_sync_task(self): + self._cancel_timeout_height_sync_task() + self._timeout_height_sync_task = asyncio.create_task(self._timeout_height_sync_process()) + + async def _timeout_height_sync_process(self): + while True: + await self.sync_timeout_height() + await asyncio.sleep(DEFAULT_TIMEOUTHEIGHT_SYNC_INTERVAL) + + def _cancel_timeout_height_sync_task(self): + if self._timeout_height_sync_task is not None: + self._timeout_height_sync_task.cancel() + self._timeout_height_sync_task = None diff --git a/pyproject.toml b/pyproject.toml index 07bbadb2..6e72c508 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "injective-py" -version = "0.9.3" +version = "0.10dev" description = "Injective Python SDK, with Exchange API Client" authors = ["Injective Labs "] license = "Apache-2.0" @@ -22,7 +22,6 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -aiocron = "*" aiohttp = "*" asyncio = "*" bech32 = "*" From a9f6842d0b804770ff6937b759d75540b0c9e1fd Mon Sep 17 00:00:00 2001 From: abel Date: Mon, 16 Oct 2023 15:47:27 -0300 Subject: [PATCH 5/6] (fix) Undo inclusion of Python 3.12 to tests execution GitHub workflow --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 95fa937f..ccde1d03 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -8,7 +8,7 @@ jobs: run-tests: strategy: matrix: - python: ["3.9", "3.10", "3.11", "3.12"] + python: ["3.9", "3.10", "3.11"] os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} env: From aa0fc44d9986ed8004981e5d05c9afa60f41dd59 Mon Sep 17 00:00:00 2001 From: Achilleas Kalantzis Date: Tue, 17 Oct 2023 19:46:27 +0300 Subject: [PATCH 6/6] chore: remove example --- .../23_LiquidablePositions.py | 30 ------------------- 1 file changed, 30 deletions(-) delete mode 100644 examples/exchange_client/derivative_exchange_rpc/23_LiquidablePositions.py diff --git a/examples/exchange_client/derivative_exchange_rpc/23_LiquidablePositions.py b/examples/exchange_client/derivative_exchange_rpc/23_LiquidablePositions.py deleted file mode 100644 index e87f67b1..00000000 --- a/examples/exchange_client/derivative_exchange_rpc/23_LiquidablePositions.py +++ /dev/null @@ -1,30 +0,0 @@ -import asyncio - -from google.protobuf import json_format - -from pyinjective.async_client import AsyncClient -from pyinjective.core.network import Network - - -async def main() -> None: - network = Network.testnet() - client = AsyncClient(network) - market_id = "0x17ef48032cb24375ba7c2e39f384e56433bcab20cbee9a7357e4cba2eb00abe6" - skip = 10 - limit = 3 - positions = await client.get_derivative_liquidable_positions( - market_id=market_id, - skip=skip, - limit=limit, - ) - print( - json_format.MessageToJson( - message=positions, - including_default_value_fields=True, - preserving_proto_field_name=True, - ) - ) - - -if __name__ == "__main__": - asyncio.get_event_loop().run_until_complete(main())