diff --git a/src/apis/orderbookapi.py b/src/apis/orderbookapi.py index 7f7af86..83c7a4f 100644 --- a/src/apis/orderbookapi.py +++ b/src/apis/orderbookapi.py @@ -16,17 +16,16 @@ FAIL_CODE, ) -PROD_BASE_URL = "https://api.cow.fi/mainnet/api/v1/" -BARN_BASE_URL = "https://barn.api.cow.fi/mainnet/api/v1/" - class OrderbookAPI: """ Class for fetching data from a Web3 API. """ - def __init__(self) -> None: + def __init__(self, chain_name: str) -> None: self.logger = get_logger() + self.prod_url_prefix = f"https://api.cow.fi/{chain_name}/api/v1/" + self.barn_url_prefix = f"https://barn.api.cow.fi/{chain_name}/api/v1/" def get_solver_competition_data(self, tx_hash: str) -> Optional[dict[str, Any]]: """ @@ -34,8 +33,12 @@ def get_solver_competition_data(self, tx_hash: str) -> Optional[dict[str, Any]]: The returned dict follows the schema outlined here: https://api.cow.fi/docs/#/default/get_api_v1_solver_competition_by_tx_hash__tx_hash_ """ - prod_endpoint_url = f"{PROD_BASE_URL}solver_competition/by_tx_hash/{tx_hash}" - barn_endpoint_url = f"{BARN_BASE_URL}solver_competition/by_tx_hash/{tx_hash}" + prod_endpoint_url = ( + f"{self.prod_url_prefix}solver_competition/by_tx_hash/{tx_hash}" + ) + barn_endpoint_url = ( + f"{self.barn_url_prefix}solver_competition/by_tx_hash/{tx_hash}" + ) solver_competition_data: Optional[dict[str, Any]] = None try: json_competition_data = requests.get( @@ -65,8 +68,8 @@ def get_order_data(self, uid: str) -> dict[str, Any] | None: The returned dict follows the schema outlined here: https://api.cow.fi/docs/#/default/get_api_v1_orders__UID_ """ - prod_endpoint_url = f"{PROD_BASE_URL}orders/{uid}" - barn_endpoint_url = f"{BARN_BASE_URL}orders/{uid}" + prod_endpoint_url = f"{self.prod_url_prefix}orders/{uid}" + barn_endpoint_url = f"{self.barn_url_prefix}orders/{uid}" order_data: Optional[dict[str, Any]] = None try: json_order_data = requests.get( diff --git a/src/apis/web3api.py b/src/apis/web3api.py index 87527f4..b17b4c8 100644 --- a/src/apis/web3api.py +++ b/src/apis/web3api.py @@ -36,6 +36,12 @@ def __init__(self) -> None: ) self.logger = get_logger() + def get_chain_id(self) -> int: + """ + Function that returns the chain id + """ + return self.web_3.eth.chain_id + def get_current_block_number(self) -> Optional[int]: """ Function that returns the current block number diff --git a/src/constants.py b/src/constants.py index 7eb39a5..b0795ee 100644 --- a/src/constants.py +++ b/src/constants.py @@ -57,3 +57,5 @@ "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36" } + +CHAIN_ID_TO_NAME = {1: "mainnet", 100: "xdai", 42161: "arbitrum_one", 8453: "base"} diff --git a/src/daemon.py b/src/daemon.py index 1a01cfb..9c638c0 100644 --- a/src/daemon.py +++ b/src/daemon.py @@ -1,4 +1,4 @@ -""" A daemon to run tests on settlements. +"""A daemon to run tests on settlements. An infinite loop is started which listens to CoW Protocol trade events. If such an event happens, the correstonding transaction hash is added to the queue of the individual tests. @@ -10,6 +10,7 @@ import time from typing import Optional from src.apis.web3api import Web3API +from src.apis.orderbookapi import OrderbookAPI from src.monitoring_tests.solver_competition_surplus_test import ( SolverCompetitionSurplusTest, ) @@ -19,7 +20,7 @@ from src.monitoring_tests.high_score_test import ( HighScoreTest, ) -from src.constants import SLEEP_TIME_IN_SEC +from src.constants import SLEEP_TIME_IN_SEC, CHAIN_ID_TO_NAME def main() -> None: @@ -27,13 +28,18 @@ def main() -> None: daemon function that runs as highlighted in docstring. """ web3_api = Web3API() + chain_id = web3_api.get_chain_id() + chain_name = CHAIN_ID_TO_NAME[chain_id] + orderbook_api = OrderbookAPI(chain_name) # initialize tests tests = [ - SolverCompetitionSurplusTest(), - MEVBlockerRefundsMonitoringTest(), - HighScoreTest(), + SolverCompetitionSurplusTest(orderbook_api), + HighScoreTest(orderbook_api), ] + # special case for mainnet as MEV Blocker only exists on mainnet + if chain_name == "mainnet": + tests.append(MEVBlockerRefundsMonitoringTest(web3_api)) start_block: Optional[int] = None diff --git a/src/monitoring_tests/combinatorial_auction_surplus_test.py b/src/monitoring_tests/combinatorial_auction_surplus_test.py index 4e82df4..3c14681 100644 --- a/src/monitoring_tests/combinatorial_auction_surplus_test.py +++ b/src/monitoring_tests/combinatorial_auction_surplus_test.py @@ -35,9 +35,9 @@ class CombinatorialAuctionSurplusTest(BaseTest): with our current mechanism. """ - def __init__(self) -> None: + def __init__(self, orderbook_api: OrderbookAPI) -> None: super().__init__() - self.orderbook_api = OrderbookAPI() + self.orderbook_api = orderbook_api def run_combinatorial_auction(self, competition_data: dict[str, Any]) -> bool: """Run combinatorial auction on competition data. diff --git a/src/monitoring_tests/cost_coverage_zero_signed_fee.py b/src/monitoring_tests/cost_coverage_zero_signed_fee.py index be0ed8e..b17e945 100644 --- a/src/monitoring_tests/cost_coverage_zero_signed_fee.py +++ b/src/monitoring_tests/cost_coverage_zero_signed_fee.py @@ -16,10 +16,10 @@ class CostCoverageForZeroSignedFee(BaseTest): sent as zero-signed fee orders from CoW Swap. """ - def __init__(self) -> None: + def __init__(self, web3_api: Web3API, orderbook_api: OrderbookAPI) -> None: super().__init__() - self.web3_api = Web3API() - self.orderbook_api = OrderbookAPI() + self.web3_api = web3_api + self.orderbook_api = orderbook_api self.cost_coverage_per_solver: Dict[str, float] = {} self.total_coverage_per_solver: Dict[str, float] = {} self.original_block = self.web3_api.get_current_block_number() diff --git a/src/monitoring_tests/high_score_test.py b/src/monitoring_tests/high_score_test.py index b96ecd5..a4980ec 100644 --- a/src/monitoring_tests/high_score_test.py +++ b/src/monitoring_tests/high_score_test.py @@ -16,9 +16,9 @@ class HighScoreTest(BaseTest): is above certain threshold """ - def __init__(self) -> None: + def __init__(self, orderbook_api: OrderbookAPI) -> None: super().__init__() - self.orderbook_api = OrderbookAPI() + self.orderbook_api = orderbook_api def compute_winning_score(self, competition_data: dict[str, Any]) -> bool: """ diff --git a/src/monitoring_tests/mev_blocker_kickbacks_test.py b/src/monitoring_tests/mev_blocker_kickbacks_test.py index f7c1525..d5481fd 100644 --- a/src/monitoring_tests/mev_blocker_kickbacks_test.py +++ b/src/monitoring_tests/mev_blocker_kickbacks_test.py @@ -19,9 +19,9 @@ class MEVBlockerRefundsMonitoringTest(BaseTest): generates a log/alert if this is the case. """ - def __init__(self) -> None: + def __init__(self, web3_api: Web3API) -> None: super().__init__() - self.web3_api = Web3API() + self.web3_api = web3_api def run(self, tx_hash: str) -> bool: """ diff --git a/src/monitoring_tests/partially_fillable_cost_coverage_test.py b/src/monitoring_tests/partially_fillable_cost_coverage_test.py index 390c704..3c8733e 100644 --- a/src/monitoring_tests/partially_fillable_cost_coverage_test.py +++ b/src/monitoring_tests/partially_fillable_cost_coverage_test.py @@ -20,10 +20,10 @@ class PartialFillCostCoverageTest(BaseTest): Class for testing fees. """ - def __init__(self) -> None: + def __init__(self, web3_api: Web3API, orderbook_api: OrderbookAPI) -> None: super().__init__() - self.web3_api = Web3API() - self.orderbook_api = OrderbookAPI() + self.web3_api = web3_api + self.orderbook_api = orderbook_api def run(self, tx_hash: str) -> bool: """ diff --git a/src/monitoring_tests/reference_solver_surplus_test.py b/src/monitoring_tests/reference_solver_surplus_test.py index 9c92303..9f97d35 100644 --- a/src/monitoring_tests/reference_solver_surplus_test.py +++ b/src/monitoring_tests/reference_solver_surplus_test.py @@ -22,10 +22,10 @@ class ReferenceSolverSurplusTest(BaseTest): the executions of these orders by a reference solver. """ - def __init__(self) -> None: + def __init__(self, web3_api: Web3API, orderbook_api: OrderbookAPI) -> None: super().__init__() - self.web3_api = Web3API() - self.orderbook_api = OrderbookAPI() + self.web3_api = web3_api + self.orderbook_api = orderbook_api self.auction_instance_api = AuctionInstanceAPI() self.solver_api = SolverAPI() diff --git a/src/monitoring_tests/solver_competition_surplus_test.py b/src/monitoring_tests/solver_competition_surplus_test.py index 05f6d66..e61600b 100644 --- a/src/monitoring_tests/solver_competition_surplus_test.py +++ b/src/monitoring_tests/solver_competition_surplus_test.py @@ -18,9 +18,9 @@ class SolverCompetitionSurplusTest(BaseTest): the different executions of these orders by other solvers in the competition. """ - def __init__(self) -> None: + def __init__(self, orderbook_api: OrderbookAPI) -> None: super().__init__() - self.orderbook_api = OrderbookAPI() + self.orderbook_api = orderbook_api def compare_orders_surplus(self, competition_data: dict[str, Any]) -> bool: """ @@ -119,7 +119,7 @@ def get_uid_order_execution( def run(self, tx_hash: str) -> bool: """ Wrapper function for the whole test. Checks if solver competition data is retrievable - and runs EBBO test, else returns True to add to list of unchecked hashes. + and runs EBBO test, else returns False to add to list of unchecked hashes. """ solver_competition_data = self.orderbook_api.get_solver_competition_data( diff --git a/src/monitoring_tests/uniform_directed_prices_test.py b/src/monitoring_tests/uniform_directed_prices_test.py index f12f917..a4464ea 100644 --- a/src/monitoring_tests/uniform_directed_prices_test.py +++ b/src/monitoring_tests/uniform_directed_prices_test.py @@ -18,9 +18,9 @@ class UniformDirectedPricesTest(BaseTest): as introduced in CIP-38, is satisfied. """ - def __init__(self) -> None: + def __init__(self, orderbook_api: OrderbookAPI) -> None: super().__init__() - self.orderbook_api = OrderbookAPI() + self.orderbook_api = orderbook_api def check_udp(self, competition_data: dict[str, Any]) -> bool: """