From baad55a35d096dfbd7dbd56cf265d1b596cde66f Mon Sep 17 00:00:00 2001 From: Tritium-VLK <11885129+Tritium-VLK@users.noreply.github.com> Date: Fri, 19 Jul 2024 20:50:21 +0200 Subject: [PATCH 1/5] add_w3_rpc_class --- bal_tools/__init__.py | 3 ++- bal_tools/drpc.py | 22 ++++++++++++++++++++++ setup.py | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 bal_tools/drpc.py diff --git a/bal_tools/__init__.py b/bal_tools/__init__.py index 6523e71..329104b 100644 --- a/bal_tools/__init__.py +++ b/bal_tools/__init__.py @@ -6,4 +6,5 @@ ) from .subgraph import Subgraph from .pools_gauges import BalPoolsGauges -from .ecosystem import Aura \ No newline at end of file +from .ecosystem import Aura +from .drpc import W3_RPC_BY_CHAIN, W3_RPC \ No newline at end of file diff --git a/bal_tools/drpc.py b/bal_tools/drpc.py new file mode 100644 index 0000000..4494010 --- /dev/null +++ b/bal_tools/drpc.py @@ -0,0 +1,22 @@ +from web3 import Web3 +from bal_addresses import AddrBook + +DRPC_NAME_OVERRIDES = { + "mainnet": "ethereum", + "zkevm": "polygon-zkevm", +} + +class W3_RPC_BY_CHAIN(): + w3_by_chain = {} + + def __init__(self, DRPC_KEY): + self.DRPC_KEY = DRPC_KEY + for chain in AddrBook.chain_ids_by_name.keys(): + drpc_chain = DRPC_NAME_OVERRIDES.get(chain, chain) + self.w3_by_chain[chain] = W3_RPC(chain, DRPC_KEY) + +class W3_RPC(): + def __init__(self, chain, DRPC_KEY): + drpc_chain = self.DRPC_NAME_OVERRIDES.get(chain, chain) + w3 = Web3(Web3.HTTPProvider(f"https://lb.drpc.org/ogrpc?network={drpc_chain}&dkey={DRPC_KEY}")) + diff --git a/setup.py b/setup.py index 7828fe4..d402795 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup, find_packages -VERSION = "0.0.6" +VERSION = "0.0.7" DESCRIPTION = "Balancer Tools" LONG_DESCRIPTION = "Balancer Maxi helper and ecosystem tools" From 053bcb5aee17975acb3cd388635dae50c4c15f82 Mon Sep 17 00:00:00 2001 From: Tritium-VLK <11885129+Tritium-VLK@users.noreply.github.com> Date: Thu, 25 Jul 2024 23:42:26 +0200 Subject: [PATCH 2/5] Don't offer chains that don't exist in the by chain class and fix naming. Update version in setup.py --- bal_tools/__init__.py | 2 +- bal_tools/drpc.py | 47 +++++++++++++++++++++++++++++++++++-------- setup.py | 2 +- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/bal_tools/__init__.py b/bal_tools/__init__.py index 329104b..ee3ea8f 100644 --- a/bal_tools/__init__.py +++ b/bal_tools/__init__.py @@ -7,4 +7,4 @@ from .subgraph import Subgraph from .pools_gauges import BalPoolsGauges from .ecosystem import Aura -from .drpc import W3_RPC_BY_CHAIN, W3_RPC \ No newline at end of file +from .drpc import Web3RpcByChain, Web3Rpc \ No newline at end of file diff --git a/bal_tools/drpc.py b/bal_tools/drpc.py index 4494010..43d5993 100644 --- a/bal_tools/drpc.py +++ b/bal_tools/drpc.py @@ -6,17 +6,48 @@ "zkevm": "polygon-zkevm", } -class W3_RPC_BY_CHAIN(): - w3_by_chain = {} - +class Web3RpcByChain: def __init__(self, DRPC_KEY): self.DRPC_KEY = DRPC_KEY + self.w3_by_chain = {} for chain in AddrBook.chain_ids_by_name.keys(): - drpc_chain = DRPC_NAME_OVERRIDES.get(chain, chain) - self.w3_by_chain[chain] = W3_RPC(chain, DRPC_KEY) + try: + w3 = Web3Rpc(chain, DRPC_KEY) + self.w3_by_chain[chain] = w3 + except ConnectionError as e: + print(f"Skipping chain {chain} due to connection error: {e}") + + def __getitem__(self, chain): + return self.w3_by_chain[chain] + + def __setitem__(self, chain, value): + self.w3_by_chain[chain] = value + + def __delitem__(self, chain): + del self.w3_by_chain[chain] + + def __iter__(self): + return iter(self.w3_by_chain) + + def keys(self): + return self.w3_by_chain.keys() + + def values(self): + return self.w3_by_chain.values() + + def items(self): + return self.w3_by_chain.items() -class W3_RPC(): +class Web3Rpc: def __init__(self, chain, DRPC_KEY): - drpc_chain = self.DRPC_NAME_OVERRIDES.get(chain, chain) - w3 = Web3(Web3.HTTPProvider(f"https://lb.drpc.org/ogrpc?network={drpc_chain}&dkey={DRPC_KEY}")) + drpc_chain = DRPC_NAME_OVERRIDES.get(chain, chain) + self.w3 = Web3(Web3.HTTPProvider(f"https://lb.drpc.org/ogrpc?network={drpc_chain}&dkey={DRPC_KEY}")) + if not self.w3.is_connected(): + raise ConnectionError(f"Unable to connect to {drpc_chain} network with provided DRPC_KEY.") + try: + self.w3.eth.block_number + except Exception as e: + raise ConnectionError(f"Error fetching latest block number: {e}, chain: {chain}, url: {self.w3.provider.endpoint_uri}") + def __getattr__(self, name): + return getattr(self.w3, name) diff --git a/setup.py b/setup.py index d402795..8530a58 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup, find_packages -VERSION = "0.0.7" +VERSION = "0.1.2" DESCRIPTION = "Balancer Tools" LONG_DESCRIPTION = "Balancer Maxi helper and ecosystem tools" From 7f702ef1ba8cd7857458217b66eca53891920587 Mon Sep 17 00:00:00 2001 From: jalbrekt85 Date: Fri, 26 Jul 2024 19:55:51 -0500 Subject: [PATCH 3/5] only init w3 on reference, drpc test --- bal_tools/drpc.py | 9 +++------ tests/conftest.py | 5 +++++ tests/test_drpc.py | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 tests/test_drpc.py diff --git a/bal_tools/drpc.py b/bal_tools/drpc.py index 43d5993..f018dad 100644 --- a/bal_tools/drpc.py +++ b/bal_tools/drpc.py @@ -10,14 +10,11 @@ class Web3RpcByChain: def __init__(self, DRPC_KEY): self.DRPC_KEY = DRPC_KEY self.w3_by_chain = {} - for chain in AddrBook.chain_ids_by_name.keys(): - try: - w3 = Web3Rpc(chain, DRPC_KEY) - self.w3_by_chain[chain] = w3 - except ConnectionError as e: - print(f"Skipping chain {chain} due to connection error: {e}") def __getitem__(self, chain): + if chain not in self.w3_by_chain: + w3 = Web3Rpc(chain, self.DRPC_KEY) + self.w3_by_chain[chain] = w3 return self.w3_by_chain[chain] def __setitem__(self, chain, value): diff --git a/tests/conftest.py b/tests/conftest.py index 5ecaa8b..2a34e03 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -91,3 +91,8 @@ def pool_snapshot_blocks(): "avalanche": 30000000, "zkevm": 1200000, } + + +@pytest.fixture(scope="module") +def DRPC_KEY(): + return os.getenv("DRPC_KEY") \ No newline at end of file diff --git a/tests/test_drpc.py b/tests/test_drpc.py new file mode 100644 index 0000000..a39b4cb --- /dev/null +++ b/tests/test_drpc.py @@ -0,0 +1,16 @@ +import pytest +from bal_tools.drpc import Web3RpcByChain, Web3Rpc +from tests.conftest import chains + + +def test_drpc_by_chain(DRPC_KEY): + if not DRPC_KEY: + pytest.skip("Skipping DRPC_KEY not set") + + w3_by_chain = Web3RpcByChain(DRPC_KEY) + assert not w3_by_chain.keys() + + for chain in chains: + assert w3_by_chain[chain].eth + + assert sorted(w3_by_chain.keys()) == sorted(chains) From 31e0df1f2a8030027729b145360c7a35834a8e76 Mon Sep 17 00:00:00 2001 From: jalbrekt85 Date: Fri, 26 Jul 2024 20:11:24 -0500 Subject: [PATCH 4/5] support dot syntax --- bal_tools/drpc.py | 26 ++++++++++++++++---------- tests/test_drpc.py | 13 ++++++++++++- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/bal_tools/drpc.py b/bal_tools/drpc.py index f018dad..194d8cd 100644 --- a/bal_tools/drpc.py +++ b/bal_tools/drpc.py @@ -9,31 +9,37 @@ class Web3RpcByChain: def __init__(self, DRPC_KEY): self.DRPC_KEY = DRPC_KEY - self.w3_by_chain = {} + self._w3_by_chain = {} def __getitem__(self, chain): - if chain not in self.w3_by_chain: + return self._get_or_create_w3(chain) + + def __getattr__(self, chain): + return self._get_or_create_w3(chain) + + def _get_or_create_w3(self, chain): + if chain not in self._w3_by_chain: w3 = Web3Rpc(chain, self.DRPC_KEY) - self.w3_by_chain[chain] = w3 - return self.w3_by_chain[chain] + self._w3_by_chain[chain] = w3 + return self._w3_by_chain[chain] def __setitem__(self, chain, value): - self.w3_by_chain[chain] = value + self._w3_by_chain[chain] = value def __delitem__(self, chain): - del self.w3_by_chain[chain] + del self._w3_by_chain[chain] def __iter__(self): - return iter(self.w3_by_chain) + return iter(self._w3_by_chain) def keys(self): - return self.w3_by_chain.keys() + return self._w3_by_chain.keys() def values(self): - return self.w3_by_chain.values() + return self._w3_by_chain.values() def items(self): - return self.w3_by_chain.items() + return self._w3_by_chain.items() class Web3Rpc: def __init__(self, chain, DRPC_KEY): diff --git a/tests/test_drpc.py b/tests/test_drpc.py index a39b4cb..133f5c1 100644 --- a/tests/test_drpc.py +++ b/tests/test_drpc.py @@ -3,7 +3,7 @@ from tests.conftest import chains -def test_drpc_by_chain(DRPC_KEY): +def test_drpc_by_chain_dict_syntax(DRPC_KEY): if not DRPC_KEY: pytest.skip("Skipping DRPC_KEY not set") @@ -14,3 +14,14 @@ def test_drpc_by_chain(DRPC_KEY): assert w3_by_chain[chain].eth assert sorted(w3_by_chain.keys()) == sorted(chains) + +def test_drpc_by_chain_dot_syntax(DRPC_KEY): + if not DRPC_KEY: + pytest.skip("Skipping DRPC_KEY not set") + + w3_by_chain = Web3RpcByChain(DRPC_KEY) + + assert not w3_by_chain.keys() + assert w3_by_chain.mainnet.eth + assert w3_by_chain.arbitrum.eth + assert list(w3_by_chain.keys()) == ["mainnet", "arbitrum"] \ No newline at end of file From 0f40f089278eeeed307a190c3df46a8b869a88ef Mon Sep 17 00:00:00 2001 From: jalbrekt85 Date: Mon, 29 Jul 2024 07:38:08 -0500 Subject: [PATCH 5/5] add drpc key to workflow --- .github/workflows/python_package.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/python_package.yaml b/.github/workflows/python_package.yaml index 93a95e4..c022fec 100644 --- a/.github/workflows/python_package.yaml +++ b/.github/workflows/python_package.yaml @@ -25,6 +25,7 @@ jobs: - name: Test with pytest env: ETHNODEURL: ${{ secrets.ETHNODEURL }} + DRPC_KEY: ${{ secrets.DRPC_KEY }} run: | pip install -r bal_tools/requirements-dev.txt pytest