Source code for eth_defi.provider.mev_blocker

"""MEV blocking RPC provider functionality.

`Malicious Extractable Value (MEV) <https://tradingstrategy.ai/glossary/mev>`__
is a problem for all trading activity on EVM-based blockchains.

It can be mitigated by using a special
JSON-RPC node that provides a private mempool.

This module provides methods to create special
:py:class:`web3.Web3` instances that

- Use MEV blocking JSON-RPC endpoint for all transactions

- Normal JSON-RPC node for reading data from the blockchain

"""
from collections import Counter
from typing import Any

from web3.providers import JSONBaseProvider
from web3.types import RPCEndpoint, RPCResponse

from eth_defi.provider.named import BaseNamedProvider

#: List of RPC methods that execution transactions
#:
TRANSACT_METHODS = (
    "eth_sendTransaction",
    "eth_sendRawTransaction",
)


[docs]class MEVBlockerProvider(BaseNamedProvider): """Routes methods that execute transaction through a special MEV proof endpoint. - Depending on whether we are sending a transaction or reading from the blockchain, switch between the JSON-RPC endpoint. - Route all outgoing transactions through a special MEV blocker endpoint """
[docs] def __init__( self, call_provider: BaseNamedProvider, transact_provider: BaseNamedProvider, transact_methods=TRANSACT_METHODS, ): super().__init__() self.call_provider = call_provider self.transact_provider = transact_provider self.transact_methods = transact_methods #: Keep tabs on how much API traffic we generate through each endpoint self.provider_counter = Counter( { "call": 0, "transact": 0, } )
[docs] def is_transact_method(self, method: RPCEndpoint) -> bool: """Does this RPC method do a transaction""" return method in self.transact_methods
def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse: if self.is_transact_method(method): self.provider_counter["transact"] += 1 return self.transact_provider.make_request(method, params) else: self.provider_counter["call"] += 1 return self.call_provider.make_request(method, params) @property def endpoint_uri(self) -> str: """Map us to the transact provider by the default""" return self.transact_provider.endpoint_uri @property def call_endpoint_uri(self) -> str: return self.call_provider.endpoint_uri