web3 7.0.0b4__py3-none-any.whl → 7.0.0b6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. web3/_utils/batching.py +217 -0
  2. web3/_utils/caching.py +26 -2
  3. web3/_utils/compat/__init__.py +1 -0
  4. web3/_utils/contracts.py +5 -5
  5. web3/_utils/events.py +20 -20
  6. web3/_utils/filters.py +6 -6
  7. web3/_utils/method_formatters.py +0 -23
  8. web3/_utils/module_testing/__init__.py +0 -3
  9. web3/_utils/module_testing/eth_module.py +442 -373
  10. web3/_utils/module_testing/module_testing_utils.py +13 -0
  11. web3/_utils/module_testing/web3_module.py +438 -17
  12. web3/_utils/rpc_abi.py +0 -18
  13. web3/contract/async_contract.py +11 -11
  14. web3/contract/base_contract.py +19 -18
  15. web3/contract/contract.py +13 -13
  16. web3/contract/utils.py +112 -4
  17. web3/eth/async_eth.py +10 -8
  18. web3/eth/eth.py +7 -6
  19. web3/exceptions.py +75 -21
  20. web3/gas_strategies/time_based.py +2 -2
  21. web3/geth.py +0 -188
  22. web3/main.py +21 -13
  23. web3/manager.py +237 -74
  24. web3/method.py +29 -9
  25. web3/middleware/base.py +43 -0
  26. web3/middleware/filter.py +18 -6
  27. web3/middleware/signing.py +2 -2
  28. web3/module.py +47 -7
  29. web3/providers/async_base.py +55 -23
  30. web3/providers/base.py +59 -26
  31. web3/providers/eth_tester/defaults.py +0 -48
  32. web3/providers/eth_tester/main.py +36 -11
  33. web3/providers/eth_tester/middleware.py +3 -8
  34. web3/providers/ipc.py +23 -8
  35. web3/providers/legacy_websocket.py +26 -1
  36. web3/providers/persistent/async_ipc.py +60 -76
  37. web3/providers/persistent/persistent.py +134 -10
  38. web3/providers/persistent/request_processor.py +98 -14
  39. web3/providers/persistent/websocket.py +43 -66
  40. web3/providers/rpc/async_rpc.py +20 -2
  41. web3/providers/rpc/rpc.py +22 -2
  42. web3/providers/rpc/utils.py +1 -10
  43. web3/tools/benchmark/node.py +2 -8
  44. web3/types.py +8 -2
  45. {web3-7.0.0b4.dist-info → web3-7.0.0b6.dist-info}/LICENSE +1 -1
  46. {web3-7.0.0b4.dist-info → web3-7.0.0b6.dist-info}/METADATA +32 -21
  47. {web3-7.0.0b4.dist-info → web3-7.0.0b6.dist-info}/RECORD +49 -49
  48. web3/_utils/module_testing/go_ethereum_personal_module.py +0 -300
  49. {web3-7.0.0b4.dist-info → web3-7.0.0b6.dist-info}/WHEEL +0 -0
  50. {web3-7.0.0b4.dist-info → web3-7.0.0b6.dist-info}/top_level.txt +0 -0
web3/module.py CHANGED
@@ -5,6 +5,8 @@ from typing import (
5
5
  Coroutine,
6
6
  Dict,
7
7
  Optional,
8
+ Sequence,
9
+ Tuple,
8
10
  TypeVar,
9
11
  Union,
10
12
  cast,
@@ -55,9 +57,43 @@ def apply_result_formatters(
55
57
  TReturn = TypeVar("TReturn")
56
58
 
57
59
 
60
+ @curry
61
+ def retrieve_request_information_for_batching(
62
+ w3: Union["AsyncWeb3", "Web3"],
63
+ module: "Module",
64
+ method: Method[Callable[..., Any]],
65
+ ) -> Union[
66
+ Callable[..., Tuple[Tuple[RPCEndpoint, Any], Sequence[Any]]],
67
+ Callable[..., Coroutine[Any, Any, Tuple[Tuple[RPCEndpoint, Any], Sequence[Any]]]],
68
+ ]:
69
+ async def async_inner(
70
+ *args: Any, **kwargs: Any
71
+ ) -> Tuple[Tuple[RPCEndpoint, Any], Sequence[Any]]:
72
+ (method_str, params), response_formatters = method.process_params(
73
+ module, *args, **kwargs
74
+ )
75
+ if isinstance(w3.provider, PersistentConnectionProvider):
76
+ w3.provider._request_processor.cache_request_information(
77
+ cast(RPCEndpoint, method_str), params, response_formatters
78
+ )
79
+ return (cast(RPCEndpoint, method_str), params), response_formatters
80
+
81
+ def inner(
82
+ *args: Any, **kwargs: Any
83
+ ) -> Tuple[Tuple[RPCEndpoint, Any], Sequence[Any]]:
84
+ (method_str, params), response_formatters = method.process_params(
85
+ module, *args, **kwargs
86
+ )
87
+ return (cast(RPCEndpoint, method_str), params), response_formatters
88
+
89
+ return async_inner if module.is_async else inner
90
+
91
+
58
92
  @curry
59
93
  def retrieve_blocking_method_call_fn(
60
- w3: "Web3", module: "Module", method: Method[Callable[..., TReturn]]
94
+ w3: "Web3",
95
+ module: "Module",
96
+ method: Method[Callable[..., TReturn]],
61
97
  ) -> Callable[..., Union[TReturn, LogFilter]]:
62
98
  def caller(*args: Any, **kwargs: Any) -> Union[TReturn, LogFilter]:
63
99
  try:
@@ -82,7 +118,9 @@ def retrieve_blocking_method_call_fn(
82
118
 
83
119
  @curry
84
120
  def retrieve_async_method_call_fn(
85
- async_w3: "AsyncWeb3", module: "Module", method: Method[Callable[..., Any]]
121
+ async_w3: "AsyncWeb3",
122
+ module: "Module",
123
+ method: Method[Callable[..., Any]],
86
124
  ) -> Callable[..., Coroutine[Any, Any, Optional[Union[RPCResponse, AsyncLogFilter]]]]:
87
125
  async def caller(*args: Any, **kwargs: Any) -> Union[RPCResponse, AsyncLogFilter]:
88
126
  try:
@@ -93,12 +131,11 @@ def retrieve_async_method_call_fn(
93
131
  return AsyncLogFilter(eth_module=module, filter_id=err.filter_id)
94
132
 
95
133
  if isinstance(async_w3.provider, PersistentConnectionProvider):
96
- # TODO: The typing does not seem to be correct for response_formatters.
97
- # For now, keep the expected typing but ignore it here.
98
134
  provider = async_w3.provider
99
135
  cache_key = provider._request_processor.cache_request_information(
100
- cast(RPCEndpoint, method_str), params, response_formatters # type: ignore # noqa: E501
136
+ cast(RPCEndpoint, method_str), params, response_formatters
101
137
  )
138
+
102
139
  try:
103
140
  method_str = cast(RPCEndpoint, method_str)
104
141
  return await async_w3.manager.send(method_str, params)
@@ -139,6 +176,9 @@ class Module:
139
176
  self.retrieve_caller_fn = retrieve_async_method_call_fn(w3, self)
140
177
  else:
141
178
  self.retrieve_caller_fn = retrieve_blocking_method_call_fn(w3, self)
179
+ self.retrieve_request_information = retrieve_request_information_for_batching(
180
+ w3, self
181
+ )
142
182
  self.w3 = w3
143
183
 
144
184
  @property
@@ -152,8 +192,8 @@ class Module:
152
192
  ) -> None:
153
193
  for method_name, method_class in methods.items():
154
194
  klass = (
155
- method_class.__get__(obj=self)()
195
+ method_class.__get__(module=self)()
156
196
  if method_class.is_property
157
- else method_class.__get__(obj=self)
197
+ else method_class.__get__(module=self)
158
198
  )
159
199
  setattr(self, method_name, klass)
@@ -5,6 +5,7 @@ from typing import (
5
5
  Any,
6
6
  Callable,
7
7
  Coroutine,
8
+ List,
8
9
  Optional,
9
10
  Set,
10
11
  Tuple,
@@ -18,6 +19,7 @@ from eth_utils import (
18
19
  )
19
20
 
20
21
  from web3._utils.caching import (
22
+ CACHEABLE_REQUESTS,
21
23
  async_handle_request_caching,
22
24
  )
23
25
  from web3._utils.encoding import (
@@ -56,41 +58,33 @@ if TYPE_CHECKING:
56
58
  )
57
59
 
58
60
 
59
- CACHEABLE_REQUESTS = cast(
60
- Set[RPCEndpoint],
61
- (
62
- "eth_chainId",
63
- "eth_getBlockByHash",
64
- "eth_getBlockTransactionCountByHash",
65
- "eth_getRawTransactionByHash",
66
- "eth_getTransactionByBlockHashAndIndex",
67
- "eth_getTransactionByHash",
68
- "eth_getUncleByBlockHashAndIndex",
69
- "eth_getUncleCountByBlockHash",
70
- "net_version",
71
- "web3_clientVersion",
72
- ),
73
- )
74
-
75
-
76
61
  class AsyncBaseProvider:
77
62
  _request_func_cache: Tuple[
78
63
  Tuple[Middleware, ...], Callable[..., Coroutine[Any, Any, RPCResponse]]
79
64
  ] = (None, None)
80
65
 
66
+ _is_batching: bool = False
67
+ _batch_request_func_cache: Tuple[
68
+ Tuple[Middleware, ...], Callable[..., Coroutine[Any, Any, List[RPCResponse]]]
69
+ ] = (None, None)
70
+
81
71
  is_async = True
82
72
  has_persistent_connection = False
83
73
  global_ccip_read_enabled: bool = True
84
74
  ccip_read_max_redirects: int = 4
85
75
 
86
76
  # request caching
87
- cache_allowed_requests: bool = False
88
- cacheable_requests: Set[RPCEndpoint] = CACHEABLE_REQUESTS
89
77
  _request_cache: SimpleCache
90
78
  _request_cache_lock: asyncio.Lock = asyncio.Lock()
91
79
 
92
- def __init__(self) -> None:
80
+ def __init__(
81
+ self,
82
+ cache_allowed_requests: bool = False,
83
+ cacheable_requests: Set[RPCEndpoint] = None,
84
+ ) -> None:
93
85
  self._request_cache = SimpleCache(1000)
86
+ self.cache_allowed_requests = cache_allowed_requests
87
+ self.cacheable_requests = cacheable_requests or CACHEABLE_REQUESTS
94
88
 
95
89
  async def request_func(
96
90
  self, async_w3: "AsyncWeb3", middleware_onion: MiddlewareOnion
@@ -109,10 +103,34 @@ class AsyncBaseProvider:
109
103
  )
110
104
  return self._request_func_cache[-1]
111
105
 
106
+ async def batch_request_func(
107
+ self, async_w3: "AsyncWeb3", middleware_onion: MiddlewareOnion
108
+ ) -> Callable[..., Coroutine[Any, Any, List[RPCResponse]]]:
109
+ middleware: Tuple[Middleware, ...] = middleware_onion.as_tuple_of_middleware()
110
+
111
+ cache_key = self._batch_request_func_cache[0]
112
+ if cache_key != middleware:
113
+ accumulator_fn = self.make_batch_request
114
+ for mw in reversed(middleware):
115
+ initialized = mw(async_w3)
116
+ # type ignore bc in order to wrap the method, we have to call
117
+ # `async_wrap_make_batch_request` with the accumulator_fn as the
118
+ # argument which breaks the type hinting for this particular case.
119
+ accumulator_fn = await initialized.async_wrap_make_batch_request( # type: ignore # noqa: E501
120
+ accumulator_fn
121
+ )
122
+ self._batch_request_func_cache = (middleware, accumulator_fn)
123
+ return self._batch_request_func_cache[-1]
124
+
112
125
  @async_handle_request_caching
113
126
  async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
114
127
  raise NotImplementedError("Providers must implement this method")
115
128
 
129
+ async def make_batch_request(
130
+ self, requests: List[Tuple[RPCEndpoint, Any]]
131
+ ) -> List[RPCResponse]:
132
+ raise NotImplementedError("Only AsyncHTTPProvider supports this method")
133
+
116
134
  async def is_connected(self, show_traceback: bool = False) -> bool:
117
135
  raise NotImplementedError("Providers must implement this method")
118
136
 
@@ -141,9 +159,9 @@ class AsyncBaseProvider:
141
159
 
142
160
 
143
161
  class AsyncJSONBaseProvider(AsyncBaseProvider):
144
- def __init__(self) -> None:
145
- super().__init__()
162
+ def __init__(self, **kwargs: Any) -> None:
146
163
  self.request_counter = itertools.count()
164
+ super().__init__(**kwargs)
147
165
 
148
166
  def encode_rpc_request(self, method: RPCEndpoint, params: Any) -> bytes:
149
167
  request_id = next(self.request_counter)
@@ -156,7 +174,8 @@ class AsyncJSONBaseProvider(AsyncBaseProvider):
156
174
  encoded = FriendlyJsonSerde().json_encode(rpc_dict, cls=Web3JsonEncoder)
157
175
  return to_bytes(text=encoded)
158
176
 
159
- def decode_rpc_response(self, raw_response: bytes) -> RPCResponse:
177
+ @staticmethod
178
+ def decode_rpc_response(raw_response: bytes) -> RPCResponse:
160
179
  text_response = str(
161
180
  to_text(raw_response) if not is_text(raw_response) else raw_response
162
181
  )
@@ -185,3 +204,16 @@ class AsyncJSONBaseProvider(AsyncBaseProvider):
185
204
  if show_traceback:
186
205
  raise ProviderConnectionError(f"Bad jsonrpc version: {response}")
187
206
  return False
207
+
208
+ # -- batch requests -- #
209
+
210
+ def encode_batch_rpc_request(
211
+ self, requests: List[Tuple[RPCEndpoint, Any]]
212
+ ) -> bytes:
213
+ return (
214
+ b"["
215
+ + b", ".join(
216
+ self.encode_rpc_request(method, params) for method, params in requests
217
+ )
218
+ + b"]"
219
+ )
web3/providers/base.py CHANGED
@@ -4,6 +4,7 @@ from typing import (
4
4
  TYPE_CHECKING,
5
5
  Any,
6
6
  Callable,
7
+ List,
7
8
  Set,
8
9
  Tuple,
9
10
  cast,
@@ -15,6 +16,7 @@ from eth_utils import (
15
16
  )
16
17
 
17
18
  from web3._utils.caching import (
19
+ CACHEABLE_REQUESTS,
18
20
  handle_request_caching,
19
21
  )
20
22
  from web3._utils.encoding import (
@@ -43,23 +45,6 @@ if TYPE_CHECKING:
43
45
  from web3 import Web3 # noqa: F401
44
46
 
45
47
 
46
- CACHEABLE_REQUESTS = cast(
47
- Set[RPCEndpoint],
48
- (
49
- "eth_chainId",
50
- "eth_getBlockByHash",
51
- "eth_getBlockTransactionCountByHash",
52
- "eth_getRawTransactionByHash",
53
- "eth_getTransactionByBlockHashAndIndex",
54
- "eth_getTransactionByHash",
55
- "eth_getUncleByBlockHashAndIndex",
56
- "eth_getUncleCountByBlockHash",
57
- "net_version",
58
- "web3_clientVersion",
59
- ),
60
- )
61
-
62
-
63
48
  class BaseProvider:
64
49
  # a tuple of (middleware, request_func)
65
50
  _request_func_cache: Tuple[Tuple[Middleware, ...], Callable[..., RPCResponse]] = (
@@ -73,13 +58,17 @@ class BaseProvider:
73
58
  ccip_read_max_redirects: int = 4
74
59
 
75
60
  # request caching
76
- cache_allowed_requests: bool = False
77
- cacheable_requests: Set[RPCEndpoint] = CACHEABLE_REQUESTS
78
61
  _request_cache: SimpleCache
79
62
  _request_cache_lock: threading.Lock = threading.Lock()
80
63
 
81
- def __init__(self) -> None:
64
+ def __init__(
65
+ self,
66
+ cache_allowed_requests: bool = False,
67
+ cacheable_requests: Set[RPCEndpoint] = None,
68
+ ) -> None:
82
69
  self._request_cache = SimpleCache(1000)
70
+ self.cache_allowed_requests = cache_allowed_requests
71
+ self.cacheable_requests = cacheable_requests or CACHEABLE_REQUESTS
83
72
 
84
73
  def request_func(
85
74
  self, w3: "Web3", middleware_onion: MiddlewareOnion
@@ -115,13 +104,14 @@ class BaseProvider:
115
104
 
116
105
 
117
106
  class JSONBaseProvider(BaseProvider):
118
- def __init__(self) -> None:
119
- self.request_counter = itertools.count()
120
- super().__init__()
107
+ _is_batching: bool = False
108
+ _batch_request_func_cache: Tuple[
109
+ Tuple[Middleware, ...], Callable[..., List[RPCResponse]]
110
+ ] = (None, None)
121
111
 
122
- def decode_rpc_response(self, raw_response: bytes) -> RPCResponse:
123
- text_response = to_text(raw_response)
124
- return cast(RPCResponse, FriendlyJsonSerde().json_decode(text_response))
112
+ def __init__(self, **kwargs: Any) -> None:
113
+ self.request_counter = itertools.count()
114
+ super().__init__(**kwargs)
125
115
 
126
116
  def encode_rpc_request(self, method: RPCEndpoint, params: Any) -> bytes:
127
117
  rpc_dict = {
@@ -133,6 +123,11 @@ class JSONBaseProvider(BaseProvider):
133
123
  encoded = FriendlyJsonSerde().json_encode(rpc_dict, Web3JsonEncoder)
134
124
  return to_bytes(text=encoded)
135
125
 
126
+ @staticmethod
127
+ def decode_rpc_response(raw_response: bytes) -> RPCResponse:
128
+ text_response = to_text(raw_response)
129
+ return cast(RPCResponse, FriendlyJsonSerde().json_decode(text_response))
130
+
136
131
  def is_connected(self, show_traceback: bool = False) -> bool:
137
132
  try:
138
133
  response = self.make_request(RPCEndpoint("web3_clientVersion"), [])
@@ -156,3 +151,41 @@ class JSONBaseProvider(BaseProvider):
156
151
  if show_traceback:
157
152
  raise ProviderConnectionError(f"Bad jsonrpc version: {response}")
158
153
  return False
154
+
155
+ # -- batch requests -- #
156
+
157
+ def batch_request_func(
158
+ self, w3: "Web3", middleware_onion: MiddlewareOnion
159
+ ) -> Callable[..., List[RPCResponse]]:
160
+ middleware: Tuple[Middleware, ...] = middleware_onion.as_tuple_of_middleware()
161
+
162
+ cache_key = self._batch_request_func_cache[0]
163
+ if cache_key != middleware:
164
+ accumulator_fn = self.make_batch_request
165
+ for mw in reversed(middleware):
166
+ initialized = mw(w3)
167
+ # type ignore bc in order to wrap the method, we have to call
168
+ # `wrap_make_batch_request` with the accumulator_fn as the argument
169
+ # which breaks the type hinting for this particular case.
170
+ accumulator_fn = initialized.wrap_make_batch_request(
171
+ accumulator_fn
172
+ ) # type: ignore # noqa: E501
173
+ self._batch_request_func_cache = (middleware, accumulator_fn)
174
+
175
+ return self._batch_request_func_cache[-1]
176
+
177
+ def encode_batch_rpc_request(
178
+ self, requests: List[Tuple[RPCEndpoint, Any]]
179
+ ) -> bytes:
180
+ return (
181
+ b"["
182
+ + b", ".join(
183
+ self.encode_rpc_request(method, params) for method, params in requests
184
+ )
185
+ + b"]"
186
+ )
187
+
188
+ def make_batch_request(
189
+ self, requests: List[Tuple[RPCEndpoint, Any]]
190
+ ) -> List[RPCResponse]:
191
+ raise NotImplementedError("Providers must implement this method")
@@ -21,7 +21,6 @@ from eth_tester.exceptions import (
21
21
  FilterNotFound,
22
22
  TransactionFailed,
23
23
  TransactionNotFound,
24
- ValidationError,
25
24
  )
26
25
  from eth_typing import (
27
26
  HexAddress,
@@ -226,18 +225,6 @@ def create_new_account(eth_tester: "EthereumTester") -> HexAddress:
226
225
  return eth_tester.add_account(_generate_random_private_key())
227
226
 
228
227
 
229
- def personal_send_transaction(eth_tester: "EthereumTester", params: Any) -> HexStr:
230
- transaction, password = params
231
-
232
- try:
233
- eth_tester.unlock_account(transaction["from"], password)
234
- transaction_hash = eth_tester.send_transaction(transaction)
235
- finally:
236
- eth_tester.lock_account(transaction["from"])
237
-
238
- return transaction_hash
239
-
240
-
241
228
  API_ENDPOINTS = {
242
229
  "web3": {
243
230
  "clientVersion": client_version,
@@ -404,41 +391,6 @@ API_ENDPOINTS = {
404
391
  "writeBlockProfile": not_implemented,
405
392
  "writeMemProfile": not_implemented,
406
393
  },
407
- "personal": {
408
- "ec_recover": not_implemented,
409
- "import_raw_key": call_eth_tester("add_account"),
410
- "list_accounts": call_eth_tester("get_accounts"),
411
- "list_wallets": not_implemented,
412
- "lock_account": excepts(
413
- ValidationError,
414
- compose(static_return(True), call_eth_tester("lock_account")),
415
- static_return(False),
416
- ),
417
- "new_account": create_new_account,
418
- "unlock_account": excepts(
419
- ValidationError,
420
- compose(static_return(True), call_eth_tester("unlock_account")),
421
- static_return(False),
422
- ),
423
- "send_transaction": personal_send_transaction,
424
- "sign": not_implemented,
425
- # deprecated
426
- "ecRecover": not_implemented,
427
- "importRawKey": call_eth_tester("add_account"),
428
- "listAccounts": call_eth_tester("get_accounts"),
429
- "lockAccount": excepts(
430
- ValidationError,
431
- compose(static_return(True), call_eth_tester("lock_account")),
432
- static_return(False),
433
- ),
434
- "newAccount": create_new_account,
435
- "unlockAccount": excepts(
436
- ValidationError,
437
- compose(static_return(True), call_eth_tester("unlock_account")),
438
- static_return(False),
439
- ),
440
- "sendTransaction": personal_send_transaction,
441
- },
442
394
  "testing": {
443
395
  "timeTravel": call_eth_tester("time_travel"),
444
396
  },
@@ -7,6 +7,7 @@ from typing import (
7
7
  Literal,
8
8
  Optional,
9
9
  Union,
10
+ cast,
10
11
  )
11
12
 
12
13
  from eth_abi import (
@@ -59,6 +60,7 @@ if TYPE_CHECKING:
59
60
 
60
61
 
61
62
  class AsyncEthereumTesterProvider(AsyncBaseProvider):
63
+ _current_request_id = 0
62
64
  _middleware = (
63
65
  default_transaction_fields_middleware,
64
66
  ethereum_tester_middleware,
@@ -99,13 +101,22 @@ class AsyncEthereumTesterProvider(AsyncBaseProvider):
99
101
  return self._request_func_cache[-1]
100
102
 
101
103
  async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
102
- return _make_request(method, params, self.api_endpoints, self.ethereum_tester)
104
+ response = _make_request(
105
+ method,
106
+ params,
107
+ self.api_endpoints,
108
+ self.ethereum_tester,
109
+ repr(self._current_request_id),
110
+ )
111
+ self._current_request_id += 1
112
+ return response
103
113
 
104
114
  async def is_connected(self, show_traceback: bool = False) -> Literal[True]:
105
115
  return True
106
116
 
107
117
 
108
118
  class EthereumTesterProvider(BaseProvider):
119
+ _current_request_id = 0
109
120
  _middleware = (
110
121
  default_transaction_fields_middleware,
111
122
  ethereum_tester_middleware,
@@ -173,23 +184,32 @@ class EthereumTesterProvider(BaseProvider):
173
184
  return self._request_func_cache[-1]
174
185
 
175
186
  def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
176
- return _make_request(method, params, self.api_endpoints, self.ethereum_tester)
187
+ response = _make_request(
188
+ method,
189
+ params,
190
+ self.api_endpoints,
191
+ self.ethereum_tester,
192
+ repr(self._current_request_id),
193
+ )
194
+ self._current_request_id += 1
195
+ return response
177
196
 
178
197
  def is_connected(self, show_traceback: bool = False) -> Literal[True]:
179
198
  return True
180
199
 
181
200
 
182
- def _make_response(result: Any, message: str = "") -> RPCResponse:
201
+ def _make_response(result: Any, response_id: str, message: str = "") -> RPCResponse:
183
202
  if isinstance(result, Exception):
184
- return RPCResponse(
203
+ return cast(
204
+ RPCResponse,
185
205
  {
186
- "id": 1,
206
+ "id": response_id,
187
207
  "jsonrpc": "2.0",
188
- "error": RPCError({"code": -32601, "message": message}),
189
- }
208
+ "error": cast(RPCError, {"code": -32601, "message": message}),
209
+ },
190
210
  )
191
211
 
192
- return RPCResponse({"id": 1, "jsonrpc": "2.0", "result": result})
212
+ return cast(RPCResponse, {"id": response_id, "jsonrpc": "2.0", "result": result})
193
213
 
194
214
 
195
215
  def _make_request(
@@ -197,6 +217,7 @@ def _make_request(
197
217
  params: Any,
198
218
  api_endpoints: Dict[str, Dict[str, Any]],
199
219
  ethereum_tester_instance: "EthereumTester",
220
+ request_id: str,
200
221
  ) -> RPCResponse:
201
222
  # do not import eth_tester derivatives until runtime,
202
223
  # it is not a default dependency
@@ -209,11 +230,15 @@ def _make_request(
209
230
  try:
210
231
  delegator = api_endpoints[namespace][endpoint]
211
232
  except KeyError as e:
212
- return _make_response(e, f"Unknown RPC Endpoint: {method}")
233
+ return _make_response(e, request_id, message=f"Unknown RPC Endpoint: {method}")
213
234
  try:
214
235
  response = delegator(ethereum_tester_instance, params)
215
236
  except NotImplementedError as e:
216
- return _make_response(e, f"RPC Endpoint has not been implemented: {method}")
237
+ return _make_response(
238
+ e,
239
+ request_id,
240
+ message=f"RPC Endpoint has not been implemented: {method}",
241
+ )
217
242
  except TransactionFailed as e:
218
243
  first_arg = e.args[0]
219
244
  try:
@@ -230,4 +255,4 @@ def _make_request(
230
255
  reason = first_arg
231
256
  raise TransactionFailed(f"execution reverted: {reason}")
232
257
  else:
233
- return _make_response(response)
258
+ return _make_response(response, request_id)
@@ -110,14 +110,14 @@ filter_request_remapper = apply_key_map(FILTER_REQUEST_KEY_MAPPING)
110
110
 
111
111
 
112
112
  FILTER_REQUEST_FORMATTERS = {
113
- "fromBlock": to_integer_if_hex,
114
- "toBlock": to_integer_if_hex,
113
+ "from_block": to_integer_if_hex,
114
+ "to_block": to_integer_if_hex,
115
115
  }
116
116
  filter_request_formatter = apply_formatters_to_dict(FILTER_REQUEST_FORMATTERS)
117
117
 
118
118
  filter_request_transformer = compose(
119
- filter_request_remapper,
120
119
  filter_request_formatter,
120
+ filter_request_remapper,
121
121
  )
122
122
 
123
123
 
@@ -285,11 +285,6 @@ request_formatters = {
285
285
  ),
286
286
  # EVM
287
287
  RPCEndpoint("evm_revert"): apply_formatters_to_args(hex_to_integer),
288
- # Personal
289
- RPCEndpoint("personal_sendTransaction"): apply_formatters_to_args(
290
- transaction_request_transformer,
291
- identity,
292
- ),
293
288
  }
294
289
 
295
290
  result_formatters: Optional[Dict[RPCEndpoint, Callable[..., Any]]] = {
web3/providers/ipc.py CHANGED
@@ -14,8 +14,11 @@ from types import (
14
14
  )
15
15
  from typing import (
16
16
  Any,
17
+ List,
18
+ Tuple,
17
19
  Type,
18
20
  Union,
21
+ cast,
19
22
  )
20
23
 
21
24
  from web3._utils.threads import (
@@ -26,6 +29,9 @@ from web3.types import (
26
29
  RPCResponse,
27
30
  )
28
31
 
32
+ from .._utils.batching import (
33
+ sort_batch_response_by_response_ids,
34
+ )
29
35
  from ..exceptions import (
30
36
  Web3TypeError,
31
37
  Web3ValueError,
@@ -135,7 +141,6 @@ class IPCProvider(JSONBaseProvider):
135
141
  self,
136
142
  ipc_path: Union[str, Path] = None,
137
143
  timeout: int = 30,
138
- *args: Any,
139
144
  **kwargs: Any,
140
145
  ) -> None:
141
146
  if ipc_path is None:
@@ -148,17 +153,12 @@ class IPCProvider(JSONBaseProvider):
148
153
  self.timeout = timeout
149
154
  self._lock = threading.Lock()
150
155
  self._socket = PersistantSocket(self.ipc_path)
151
- super().__init__()
156
+ super().__init__(**kwargs)
152
157
 
153
158
  def __str__(self) -> str:
154
159
  return f"<{self.__class__.__name__} {self.ipc_path}>"
155
160
 
156
- def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
157
- self.logger.debug(
158
- f"Making request IPC. Path: {self.ipc_path}, Method: {method}"
159
- )
160
- request = self.encode_rpc_request(method, params)
161
-
161
+ def _make_request(self, request: bytes) -> RPCResponse:
162
162
  with self._lock, self._socket as sock:
163
163
  try:
164
164
  sock.sendall(request)
@@ -189,6 +189,21 @@ class IPCProvider(JSONBaseProvider):
189
189
  timeout.sleep(0)
190
190
  continue
191
191
 
192
+ def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
193
+ self.logger.debug(
194
+ f"Making request IPC. Path: {self.ipc_path}, Method: {method}"
195
+ )
196
+ request = self.encode_rpc_request(method, params)
197
+ return self._make_request(request)
198
+
199
+ def make_batch_request(
200
+ self, requests: List[Tuple[RPCEndpoint, Any]]
201
+ ) -> List[RPCResponse]:
202
+ self.logger.debug(f"Making batch request IPC. Path: {self.ipc_path}")
203
+ request_data = self.encode_batch_rpc_request(requests)
204
+ response = cast(List[RPCResponse], self._make_request(request_data))
205
+ return sort_batch_response_by_response_ids(response)
206
+
192
207
 
193
208
  # A valid JSON RPC response can only end in } or ] http://www.jsonrpc.org/specification
194
209
  def has_valid_json_rpc_ending(raw_response: bytes) -> bool: