diff --git a/silverback/middlewares.py b/silverback/middlewares.py index 9ebe4483..73ff4302 100644 --- a/silverback/middlewares.py +++ b/silverback/middlewares.py @@ -1,5 +1,6 @@ -from typing import Any +from typing import TYPE_CHECKING, Any +from ape.api import AccountAPI from ape.logging import logger from ape.types import ContractLog from ape.utils import ManagerAccessMixin @@ -9,9 +10,12 @@ from silverback.types import TaskType from silverback.utils import hexbytes_dict +if TYPE_CHECKING: + from silverback.settings import Settings + class SilverbackMiddleware(TaskiqMiddleware, ManagerAccessMixin): - def __init__(self, *args, **kwargs): + def __init__(self, silverback_settings: "Settings", *args, **kwargs): def compute_block_time() -> int: genesis = self.chain_manager.blocks[0] head = self.chain_manager.blocks.head @@ -23,6 +27,12 @@ def compute_block_time() -> int: self.block_time = self.chain_manager.provider.network.block_time or compute_block_time() + self.signer: AccountAPI | None = None + if signer := silverback_settings.get_signer(): + self.signer = signer + self.last_nonce = self.signer.nonce + # TODO: Figure out a way to determine nonce tracking without RPC call + def pre_send(self, message: TaskiqMessage) -> TaskiqMessage: # TODO: Necessary because bytes/HexBytes doesn't encode/deocde well for some reason def fix_dict(data: dict, recurse_count: int = 0) -> dict: @@ -89,6 +99,13 @@ def pre_execute(self, message: TaskiqMessage) -> TaskiqMessage: return message def post_execute(self, message: TaskiqMessage, result: TaskiqResult): + if self.signer and (current_nonce := self.signer.nonce) > self.last_nonce: + txns_by_nonce = result.labels["txns_by_nonce"] = list( + range(self.last_nonce, current_nonce) + ) + logger.info(f"Sent {current_nonce - self.last_nonce} transactions(s): {txns_by_nonce}") + self.last_nonce = current_nonce + if self.block_time: percentage_time = 100 * (result.execution_time / self.block_time) percent_display = f" ({percentage_time:.1f}%)" diff --git a/silverback/recorder.py b/silverback/recorder.py index 70e521bc..bf6b2783 100644 --- a/silverback/recorder.py +++ b/silverback/recorder.py @@ -25,6 +25,7 @@ class TaskResult(BaseModel): # System Metrics here (must default to None in case they are missing) block_number: int | None = None + txns_by_nonce: list[int] = [] # Custom user metrics here metrics: Datapoints @@ -46,6 +47,9 @@ def _extract_system_metrics(cls, labels: dict) -> dict: if block_number := labels.get("block_number"): metrics["block_number"] = int(block_number) + if txns_by_nonce := labels.get("txns_by_nonce"): + metrics["txns_by_nonce"] = txns_by_nonce + return metrics @classmethod