From 4101b32a1d806e560a7455d54437d82a6047f811 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 22 Jul 2025 12:32:37 +0200 Subject: [PATCH 01/11] feat: remove brownie dependency --- bal_tools/requirements.txt | 1 - setup.py | 1 - 2 files changed, 2 deletions(-) diff --git a/bal_tools/requirements.txt b/bal_tools/requirements.txt index 7f2f003..ebef3f3 100644 --- a/bal_tools/requirements.txt +++ b/bal_tools/requirements.txt @@ -1,5 +1,4 @@ wheel -git+https://github.com/BalancerMaxis/brownie.git@v1.20.x#egg=eth-brownie pathlib>=1.0 numpy==1.26.4 pandas diff --git a/setup.py b/setup.py index bda2309..8e0d9e3 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,6 @@ url="https://github.com/BalancerMaxis/bal_tools", install_requires=[ "wheel", - "eth-brownie @ git+https://github.com/BalancerMaxis/brownie.git@v1.20.x", "pathlib>=1.0", "numpy==1.26.4", "pandas", From e5694c11f5a4bfabd3821a031c2362177a3bdd7e Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Tue, 22 Jul 2025 12:46:55 +0200 Subject: [PATCH 02/11] chore: bump version number --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8e0d9e3..400e546 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup, find_packages -VERSION = "0.1.18" +VERSION = "0.1.19" DESCRIPTION = "Balancer Tools" LONG_DESCRIPTION = "Balancer Maxi helper and ecosystem tools" From 2e8f3476e1801befc6e8ddbf750e100c8f5b0bb8 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Thu, 31 Jul 2025 13:13:57 +0200 Subject: [PATCH 03/11] fix: add web3>=6 --- bal_tools/requirements.txt | 1 + setup.py | 1 + 2 files changed, 2 insertions(+) diff --git a/bal_tools/requirements.txt b/bal_tools/requirements.txt index ebef3f3..1650d4e 100644 --- a/bal_tools/requirements.txt +++ b/bal_tools/requirements.txt @@ -1,4 +1,5 @@ wheel +web3>=6.0.0 pathlib>=1.0 numpy==1.26.4 pandas diff --git a/setup.py b/setup.py index 400e546..f54183e 100644 --- a/setup.py +++ b/setup.py @@ -23,6 +23,7 @@ url="https://github.com/BalancerMaxis/bal_tools", install_requires=[ "wheel", + "web3>=6.0.0", "pathlib>=1.0", "numpy==1.26.4", "pandas", From 8927d2b247d3beb4364872d62a571be13b8d3e61 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Thu, 31 Jul 2025 13:15:52 +0200 Subject: [PATCH 04/11] fix: add dotenv dep --- bal_tools/requirements.txt | 1 + setup.py | 1 + 2 files changed, 2 insertions(+) diff --git a/bal_tools/requirements.txt b/bal_tools/requirements.txt index 1650d4e..b9c4332 100644 --- a/bal_tools/requirements.txt +++ b/bal_tools/requirements.txt @@ -9,3 +9,4 @@ gql[requests] pydantic json-fix lxml +dontenv diff --git a/setup.py b/setup.py index f54183e..6145aa0 100644 --- a/setup.py +++ b/setup.py @@ -33,6 +33,7 @@ "pydantic", "json-fix", "lxml", + "dontenv", ], keywords=["python", "first package"], classifiers=[ From 9bf91955114db12e149f9eba62c3000eb6a89b4b Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Thu, 31 Jul 2025 13:19:58 +0200 Subject: [PATCH 05/11] fix: typo --- bal_tools/requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bal_tools/requirements.txt b/bal_tools/requirements.txt index b9c4332..60b5305 100644 --- a/bal_tools/requirements.txt +++ b/bal_tools/requirements.txt @@ -9,4 +9,4 @@ gql[requests] pydantic json-fix lxml -dontenv +dotenv diff --git a/setup.py b/setup.py index 6145aa0..93e2dcc 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ "pydantic", "json-fix", "lxml", - "dontenv", + "dotenv", ], keywords=["python", "first package"], classifiers=[ From 8d920a632bc4346e657682a0910a7d424cda55b8 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 23 Jul 2025 10:28:58 +0200 Subject: [PATCH 06/11] fix: hyperevm has different slug for drpc url --- bal_tools/drpc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bal_tools/drpc.py b/bal_tools/drpc.py index 25b59dd..1af0edc 100644 --- a/bal_tools/drpc.py +++ b/bal_tools/drpc.py @@ -5,6 +5,7 @@ DRPC_NAME_OVERRIDES = { "mainnet": "ethereum", "zkevm": "polygon-zkevm", + "hyperevm": "hyperliquid", } ADAPTER = HTTPAdapter( pool_connections=20, From 5fb9700293d77457f2259e3c615d62869248793a Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 23 Jul 2025 10:33:27 +0200 Subject: [PATCH 07/11] fix: add hyperevm to core pools template --- bal_tools/pools_gauges.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bal_tools/pools_gauges.py b/bal_tools/pools_gauges.py index d1a3c09..107c733 100644 --- a/bal_tools/pools_gauges.py +++ b/bal_tools/pools_gauges.py @@ -298,6 +298,7 @@ def build_core_pools( "base": {}, "mode": {}, "fraxtal": {}, + "hyperevm": {}, "optimism": {}, } From 37660a9f23877531057a25fc5898b020ae3563bd Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 23 Jul 2025 11:03:21 +0200 Subject: [PATCH 08/11] fix: not all chains have v2 deployments --- bal_tools/subgraph.py | 147 +++++++++++++++++++++++------------------ tests/test_subgraph.py | 9 +++ 2 files changed, 91 insertions(+), 65 deletions(-) diff --git a/bal_tools/subgraph.py b/bal_tools/subgraph.py index eead922..fb6aac2 100644 --- a/bal_tools/subgraph.py +++ b/bal_tools/subgraph.py @@ -131,6 +131,8 @@ def get_subgraph_url_from_backend_config(self, subgraph: str) -> str: if subgraph not in ts_keys_map: return None url = config["subgraphs"][ts_keys_map[subgraph]] + if not url: + return None if "${env.THEGRAPH_API_KEY_BALANCER}" in url: graph_api_key = os.getenv("GRAPH_API_KEY") if graph_api_key: @@ -146,9 +148,10 @@ def get_subgraph_url_from_backend_config(self, subgraph: str) -> str: f"`GRAPH_API_KEY` not set. may be rate limited or have stale data for subgraph:{subgraph} url:{url}", UserWarning, ) + return None + return url except: return None - return None def get_subgraph_url_vault_v3(self, chain: str) -> str: graph_api_key = os.getenv("GRAPH_API_KEY") @@ -184,27 +187,30 @@ def get_subgraph_url_frontendv2(self, subgraph): chain_url_slug = "gnosis-chain" if self.chain == "gnosis" else self.chain config_file = f"https://raw.githubusercontent.com/balancer/frontend-v2/master/src/lib/config/{chain_url_slug}/index.ts" found_magic_word = False - with urlopen(config_file) as f: - for line in f: - if found_magic_word or magic_word + " `" in str(line): - # url is on this line - r = re.search("`(.*)`", line.decode("utf-8")) - try: - url = r.group(1) - if urlparse(url).scheme in ["http", "https"]: - graph_api_key = os.getenv("GRAPH_API_KEY") - if "${keys.graph}" in url and not graph_api_key: - warnings.warn( - f"`GRAPH_API_KEY` not set. may be rate limited or have stale data for subgraph:{subgraph} url:{url}", - UserWarning, - ) - break - return url.replace("${keys.graph}", graph_api_key) - except AttributeError: - break - if magic_word in str(line): - # url is on next line, return it on the next iteration - found_magic_word = True + try: + with urlopen(config_file) as f: + for line in f: + if found_magic_word or magic_word + " `" in str(line): + # url is on this line + r = re.search("`(.*)`", line.decode("utf-8")) + try: + url = r.group(1) + if urlparse(url).scheme in ["http", "https"]: + graph_api_key = os.getenv("GRAPH_API_KEY") + if "${keys.graph}" in url and not graph_api_key: + warnings.warn( + f"`GRAPH_API_KEY` not set. may be rate limited or have stale data for subgraph:{subgraph} url:{url}", + UserWarning, + ) + break + return url.replace("${keys.graph}", graph_api_key) + except AttributeError: + break + if magic_word in str(line): + # url is on next line, return it on the next iteration + found_magic_word = True + except: + pass return None def get_subgraph_url_sdk(self, subgraph): @@ -219,35 +225,38 @@ def get_subgraph_url_sdk(self, subgraph): sdk_file = f"https://raw.githubusercontent.com/balancer/balancer-sdk/develop/balancer-js/src/lib/constants/config.ts" found_magic_word = False urls_reached = False - with urlopen(sdk_file) as f: - for line in f: - if "[Network." in str(line): - chain_detected = ( - str(line).split("[Network.")[1].split("]")[0].lower() - ) - if chain_detected == self.chain: - for line in f: - if "urls: {" in str(line) or urls_reached: - urls_reached = True - if "}," in str(line): - return None - if found_magic_word: - url = ( - line.decode("utf-8") - .strip() - .split(",")[0] - .strip(" ,'") - ) - url = re.sub( - r"(\s|\u180B|\u200B|\u200C|\u200D|\u2060|\uFEFF)+", - "", - url, - ) - if urlparse(url).scheme in ["http", "https"]: - return url - if magic_word in str(line): - # url is on next line, return it on the next iteration - found_magic_word = True + try: + with urlopen(sdk_file) as f: + for line in f: + if "[Network." in str(line): + chain_detected = ( + str(line).split("[Network.")[1].split("]")[0].lower() + ) + if chain_detected == self.chain: + for line in f: + if "urls: {" in str(line) or urls_reached: + urls_reached = True + if "}," in str(line): + return None + if found_magic_word: + url = ( + line.decode("utf-8") + .strip() + .split(",")[0] + .strip(" ,'") + ) + url = re.sub( + r"(\s|\u180B|\u200B|\u200C|\u200D|\u2060|\uFEFF)+", + "", + url, + ) + if urlparse(url).scheme in ["http", "https"]: + return url + if magic_word in str(line): + # url is on next line, return it on the next iteration + found_magic_word = True + except: + pass return None def get_subgraph_url_legacy(self, subgraph): @@ -262,20 +271,28 @@ def get_subgraph_url_legacy(self, subgraph): config_file = f"https://raw.githubusercontent.com/balancer/frontend-v2/master/src/lib/config/{chain_url_slug}/index.ts" found_magic_word = False - with urlopen(config_file) as f: - for line in f: - if found_magic_word: - url = line.decode("utf-8").strip().strip(" ,'") - if urlparse(url).scheme in ["http", "https"]: - return url - if magic_word + " " in str(line): - # url is on same line - url = line.decode("utf-8").split(magic_word)[1].strip().strip(",'") - if urlparse(url).scheme in ["http", "https"]: - return url - if magic_word in str(line): - # url is on next line, return it on the next iteration - found_magic_word = True + try: + with urlopen(config_file) as f: + for line in f: + if found_magic_word: + url = line.decode("utf-8").strip().strip(" ,'") + if urlparse(url).scheme in ["http", "https"]: + return url + if magic_word + " " in str(line): + # url is on same line + url = ( + line.decode("utf-8") + .split(magic_word)[1] + .strip() + .strip(",'") + ) + if urlparse(url).scheme in ["http", "https"]: + return url + if magic_word in str(line): + # url is on next line, return it on the next iteration + found_magic_word = True + except: + pass return None def fetch_graphql_data( diff --git a/tests/test_subgraph.py b/tests/test_subgraph.py index d8b9124..08eb2fc 100644 --- a/tests/test_subgraph.py +++ b/tests/test_subgraph.py @@ -112,6 +112,15 @@ def test_find_all_subgraph_urls( pytest.skip( f"No {subgraph_type} subgraph exists on {subgraph_all_chains.chain}" ) + if subgraph_all_chains.chain == "hyperevm" and subgraph_type in [ + "core", + "gauges", + "blocks", + "aura", + ]: + pytest.skip( + f"No {subgraph_type} subgraph exists on {subgraph_all_chains.chain} - V3 only chain" + ) if subgraph_type in [ "vault-v3", "pools-v3", From 5a21d8cce7513905f9dd5ba5abba1ab401b934eb Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 23 Jul 2025 11:40:22 +0200 Subject: [PATCH 09/11] fix: replace newly introduced env var --- bal_tools/subgraph.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/bal_tools/subgraph.py b/bal_tools/subgraph.py index fb6aac2..146c77b 100644 --- a/bal_tools/subgraph.py +++ b/bal_tools/subgraph.py @@ -133,14 +133,21 @@ def get_subgraph_url_from_backend_config(self, subgraph: str) -> str: url = config["subgraphs"][ts_keys_map[subgraph]] if not url: return None - if "${env.THEGRAPH_API_KEY_BALANCER}" in url: + if ( + "${env.THEGRAPH_API_KEY_BALANCER}" or "${env.THEGRAPH_API_KEY_FANTOM}" + ) in url: graph_api_key = os.getenv("GRAPH_API_KEY") if graph_api_key: try: - return url.replace( + url = url.replace( "${env.THEGRAPH_API_KEY_BALANCER}", os.getenv("GRAPH_API_KEY"), ) + url = url.replace( + "${env.THEGRAPH_API_KEY_FANTOM}", + os.getenv("GRAPH_API_KEY"), + ) + return url except: return None else: From 12fce356923f8b3374b2ce0889ae669bfc8c2872 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 23 Jul 2025 11:43:36 +0200 Subject: [PATCH 10/11] fix: if logic --- bal_tools/subgraph.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bal_tools/subgraph.py b/bal_tools/subgraph.py index 146c77b..f311237 100644 --- a/bal_tools/subgraph.py +++ b/bal_tools/subgraph.py @@ -133,9 +133,9 @@ def get_subgraph_url_from_backend_config(self, subgraph: str) -> str: url = config["subgraphs"][ts_keys_map[subgraph]] if not url: return None - if ( - "${env.THEGRAPH_API_KEY_BALANCER}" or "${env.THEGRAPH_API_KEY_FANTOM}" - ) in url: + if ("${env.THEGRAPH_API_KEY_BALANCER}" in url) or ( + "${env.THEGRAPH_API_KEY_FANTOM}" in url + ): graph_api_key = os.getenv("GRAPH_API_KEY") if graph_api_key: try: From f26e60ac55af7144ddd19f1d69476e6cf086dcd7 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 23 Jul 2025 12:08:25 +0200 Subject: [PATCH 11/11] fix: new aura subgraphs have breaking changes --- bal_tools/subgraph.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bal_tools/subgraph.py b/bal_tools/subgraph.py index f311237..0e8990b 100644 --- a/bal_tools/subgraph.py +++ b/bal_tools/subgraph.py @@ -97,6 +97,8 @@ def get_subgraph_url(self, subgraph="core") -> str: - https url of the subgraph """ # before anything else, try to get the url from the latest backend config + if subgraph == "aura": + return AURA_SUBGRAPHS_BY_CHAIN.get(self.chain, None) url = self.get_subgraph_url_from_backend_config(subgraph) if url: return url @@ -104,8 +106,6 @@ def get_subgraph_url(self, subgraph="core") -> str: if self.chain == "sepolia": return "https://test-api-v3.balancer.fi" return "https://api-v3.balancer.fi" - if subgraph == "aura": - return AURA_SUBGRAPHS_BY_CHAIN.get(self.chain, None) if subgraph == "vault-v3": return self.get_subgraph_url_vault_v3(self.chain) if subgraph == "pools-v3":