Source code for eth_defi.event_reader.fast_json_rpc

"""JSON-RPC decoding optimised for web3.py.

Monkey-patches JSON decoder to use ujson.
"""

import logging
from json import JSONDecodeError
from typing import Any, cast

import ujson
from web3 import Web3
from web3._utils.request import get_response_from_post_request
from web3.providers import JSONBaseProvider
from web3.providers.rpc import HTTPProvider
from web3.types import RPCEndpoint, RPCResponse

logger = logging.getLogger(__name__)


[docs]class PartialHttpResponseException(JSONDecodeError): """IPCProvider expects JSONDecodeErrors, not value errors."""
def _fast_decode_rpc_response(raw_response: bytes) -> RPCResponse: """Uses ujson for speeding up JSON decoding instead of web3.py default JSON.""" try: decoded = ujson.loads(raw_response) except ValueError as e: # We received partial JSON-RPC response over IPC. # Signal the underlying stack to keep reading # See IPCProvider.make_request() raise PartialHttpResponseException("Suspected partial HTTP response", "", 0) from e return cast(RPCResponse, decoded) def _make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse: """Add response headers logging in case of exception raised.""" request_data = self.encode_rpc_request(method, params) raw_response = get_response_from_post_request( self.endpoint_uri, data=request_data, **self.get_request_kwargs(), ) raw_response.raise_for_status() try: return _fast_decode_rpc_response(raw_response.content) except Exception as e: logger.error( "Unexpected decode RPC response error: %s, current provider ID is %s", str(e), raw_response.headers.get("x-drpc-provider-id", ""), extra={"response_headers": raw_response.headers}, ) raise
[docs]def patch_provider(provider: JSONBaseProvider): """Monkey-patch web3.py provider for faster JSON decoding and additional logging.""" if isinstance(provider, HTTPProvider): provider.make_request = _make_request.__get__(provider) provider.decode_rpc_response = _fast_decode_rpc_response
[docs]def patch_web3(web3: Web3): """Monkey-patch web3.py provider for faster JSON decoding and additional logging. This greatly improves JSON-RPC API access speeds, when fetching multiple and large responses. Example: .. code-block:: python from eth_defi.event_reader.fast_json_rpc import patch_web3 patch_web3(web3) """ patch_provider(web3.provider)