-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(docs): Remove outdated network endpoints and add endpoint check a…
…ction (#177)
- Loading branch information
1 parent
3710b43
commit b924ce4
Showing
11 changed files
with
429 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
name: Check Endpoints | ||
|
||
on: | ||
pull_request: | ||
paths: | ||
- docs/develop/api/networks.mdx | ||
- scripts/check_endpoints/** | ||
schedule: | ||
- cron: '0 0 * * 0' # This cron expression schedules the workflow to run every Sunday at midnight UTC | ||
workflow_dispatch: # allows manual triggering | ||
|
||
|
||
jobs: | ||
check-endpoints: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
|
||
- name: Set up Python | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: '3.9' | ||
|
||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install -r scripts/check_endpoints/requirements.txt | ||
- name: Run endpoints check | ||
run: python scripts/check_endpoints/main.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Python cache | ||
__pycache__/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
""" | ||
This file contains the logic to extract the available endpoints | ||
from the Markdown file of the docs. | ||
""" | ||
|
||
import os | ||
import re | ||
from dataclasses import dataclass | ||
from typing import List, Union | ||
|
||
|
||
@dataclass | ||
class Endpoint: | ||
address: str | ||
category: str | ||
provider: str | ||
|
||
|
||
ENDPOINT_PATTERN = re.compile(r'\|\s*`(?P<endpoint>[^`]+)`\s*\|\s*`(?P<type1>[^`]+)`\s*`(?P<type2>[^`]+)`\s*\|\s*\[(?P<provider>[^\]]+)\]'"") | ||
|
||
|
||
def get_endpoint_from_line(line: str) -> Union[Endpoint, None]: | ||
""" | ||
This method extracts the information of a given endpoint | ||
from one line of the Markdown table. | ||
""" | ||
match = ENDPOINT_PATTERN.search(line) | ||
if not match: | ||
return None | ||
|
||
return Endpoint( | ||
address=match.group("endpoint"), | ||
category=f'{match.group("type1")} {match.group("type2")}', | ||
provider=match.group("provider") | ||
) | ||
|
||
|
||
def extract_endpoints(contents: List[str]) -> List[List[str]]: | ||
""" | ||
This function extracts the available endpoints | ||
for testnet and mainnet from the given file contents. | ||
""" | ||
testnet_endpoints = [] | ||
mainnet_endpoints = [] | ||
|
||
extract_mainnet = False | ||
extract_testnet = False | ||
|
||
for line in contents: | ||
if line[0] not in ["#", "|"]: | ||
continue | ||
|
||
if "### Mainnet" in line: | ||
extract_mainnet = True | ||
extract_testnet = False | ||
continue | ||
elif "### Testnet" in line: | ||
extract_mainnet = False | ||
extract_testnet = True | ||
continue | ||
elif line[0] != "|": | ||
continue | ||
|
||
endpoint = get_endpoint_from_line(line) | ||
if endpoint is None: | ||
continue | ||
|
||
if extract_mainnet: | ||
mainnet_endpoints.append(endpoint) | ||
continue | ||
|
||
if extract_testnet: | ||
testnet_endpoints.append(endpoint) | ||
continue | ||
|
||
raise ValueError(f"unexpected condition: got endpoint {endpoint.address} but neither testnet nor mainnet is active to be extracted") | ||
|
||
return mainnet_endpoints, testnet_endpoints | ||
|
||
|
||
def get_endpoints(file: str) -> List[str]: | ||
""" | ||
This method tries to extract the list of available endpoints from | ||
from the given docs file. | ||
""" | ||
if not os.path.exists(file): | ||
raise FileNotFoundError(f"{file} does not exist") | ||
|
||
with open(file, "r", encoding="utf-8") as f: | ||
contents = f.readlines() | ||
|
||
return extract_endpoints(contents) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
""" | ||
This tool checks the list of available endpoints for their functionality. | ||
Any non-responsive endpoints are being flagged to be either discussed | ||
with the corresponding partners or removed. | ||
""" | ||
|
||
from typing import Union | ||
from endpoints import Endpoint, get_endpoints | ||
from queries import query_endpoint | ||
|
||
ENDPOINTS_FILE = "docs/develop/api/networks.mdx" | ||
|
||
|
||
def print_output(endpoint: Endpoint, ok: Union[bool, None]): | ||
ok_emoji = "❓" if ok is None else ("✅" if ok else "❌") | ||
print(f" {ok_emoji} - {endpoint.address}") | ||
|
||
|
||
def check_endpoints(file: str) -> bool: | ||
""" | ||
This function contains the main logic of the script, | ||
which gets the list of available endpoints on the docs | ||
and runs a query to all of the supported endpoint types. | ||
""" | ||
failed_endpoints = [] | ||
mainnet_endpoints, testnet_endpoints = get_endpoints(file) | ||
|
||
print("\n--------------\nChecking mainnet endpoints") | ||
for endpoint in mainnet_endpoints: | ||
ok = query_endpoint(endpoint) | ||
if ok is False: | ||
failed_endpoints.append(endpoint.address) | ||
|
||
print_output(endpoint, ok) | ||
|
||
print("\n--------------\nChecking testnet endpoints") | ||
for endpoint in testnet_endpoints: | ||
ok = query_endpoint(endpoint) | ||
if ok is False: | ||
failed_endpoints.append(endpoint.address) | ||
|
||
print_output(endpoint, ok) | ||
|
||
return failed_endpoints == [] | ||
|
||
|
||
if __name__ == "__main__": | ||
all_passed = check_endpoints(ENDPOINTS_FILE) | ||
if not all_passed: | ||
raise ValueError("some endpoints failed to return a response; check the output") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
""" | ||
This file contains the required logic to | ||
call a simple query on a given endpoint | ||
based on the type of endpoint. | ||
""" | ||
|
||
from endpoints import Endpoint | ||
import requests | ||
from typing import Union | ||
|
||
|
||
def query_endpoint(ep: Endpoint) -> Union[bool, None]: | ||
""" | ||
This function queries an endpoint based on its type. | ||
""" | ||
if ep.category == "Ethereum JSON-RPC": | ||
return query_json_rpc(ep.address) | ||
elif ep.category == "Cosmos REST": | ||
return query_cosmos_rest(ep.address) | ||
elif ep.category == "Tendermint RPC": | ||
return query_tendermint_rpc(ep.address) | ||
else: | ||
return None | ||
|
||
|
||
def query_json_rpc(address: str) -> bool: | ||
""" | ||
This method queries the latest block on the Ethereum JSON-RPC. | ||
""" | ||
try: | ||
response = requests.post( | ||
address, | ||
json={ | ||
"jsonrpc":"2.0", | ||
"method":"eth_blockNumber", | ||
"params":[], | ||
"id":83 | ||
} | ||
) | ||
return response.status_code == requests.codes.OK | ||
except Exception as e: | ||
print(f"failed to query JSON-RPC endpoint {address}: {e}") | ||
return False | ||
|
||
|
||
def query_cosmos_rest(address: str) -> bool: | ||
""" | ||
This method queries the latest block on the Cosmos REST. | ||
""" | ||
try: | ||
full_address = f"{address}/cosmos/base/tendermint/v1beta1/blocks/latest" | ||
response = requests.get(full_address) | ||
return response.status_code == requests.codes.OK | ||
except Exception as e: | ||
print(f"failed to query Cosmos REST endpoint {address}: {e}") | ||
return False | ||
|
||
|
||
def query_tendermint_rpc(address: str) -> bool: | ||
""" | ||
This method queries the latest block on the Tendermint RPC. | ||
""" | ||
try: | ||
response = requests.get(f"{address}/block") | ||
return response.status_code == requests.codes.OK | ||
except Exception as e: | ||
print(f"failed to query Tendermint RPC endpoint {address}: {e}") | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
certifi==2024.8.30 | ||
charset-normalizer==3.4.0 | ||
exceptiongroup==1.2.0 | ||
idna==3.10 | ||
iniconfig==2.0.0 | ||
packaging==24.0 | ||
pluggy==1.4.0 | ||
pytest==8.1.1 | ||
requests==2.32.3 | ||
tomli==2.0.1 | ||
urllib3==2.2.3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
""" | ||
This file contains the tests for the logic | ||
that is extracting the available endpoints | ||
from the Markdown file. | ||
""" | ||
|
||
import os | ||
import sys | ||
|
||
sys.path.append(os.path.dirname(__file__)) | ||
|
||
from endpoints import Endpoint, get_endpoint_from_line, get_endpoints | ||
|
||
|
||
def test_get_endpoint_from_line_pass(): | ||
assert get_endpoint_from_line( | ||
"| `https://evmos.lava.build` | `Ethereum` `JSON-RPC` | [Lava Network](https://lavanet.xyz) | Pruned |" | ||
) == Endpoint( | ||
address="https://evmos.lava.build", | ||
category="Ethereum JSON-RPC", | ||
provider="Lava Network" | ||
) | ||
|
||
|
||
def test_get_endpoints_pass(): | ||
mainnet, testnet = get_endpoints(os.path.join(os.path.dirname(__file__), "testdata/networks.mdx")) | ||
assert len(mainnet) > 0, "failed to get mainnet endpoints" | ||
assert len(testnet) > 0, "failed to get testnet endpoints" |
Oops, something went wrong.