Skip to content

Commit 9940bde

Browse files
authored
Raise new MethodUnavailable error for methods that are unavailable (#2796)
* Raise new MethodUnavailable error if the JSON-RPC method is not supported by the provider * Add eth-tester MethodNotFound response format * Add newsfragment, add to migration guide
1 parent d64c987 commit 9940bde

File tree

5 files changed

+46
-0
lines changed

5 files changed

+46
-0
lines changed

docs/v6_migration.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ Other Misc Changes
9292

9393
- ``InfuraKeyNotFound`` exception has been changed to ``InfuraProjectIdNotFound``
9494
- ``SolidityError`` has been removed in favor of ``ContractLogicError``
95+
- When a method is unavailable from a node provider (i.e. a response error
96+
code of -32601 is returned), a ``MethodUnavailable`` error is
97+
now raised instead of ``ValueError``
9598

9699
Removals
97100
~~~~~~~~

newsfragments/2796.breaking.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
When a method is not supported by a node provider, raise a MethodUnavailable error instead of the generic ValueError.

tests/core/manager/test_response_formatters.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
BadResponseFormat,
1414
BlockNotFound,
1515
ContractLogicError,
16+
MethodUnavailable,
1617
TransactionNotFound,
1718
)
1819

@@ -32,6 +33,17 @@
3233
"message": "You cannot query logs for more than 10000 blocks at once.",
3334
"method": "eth_getLogs",
3435
}
36+
METHOD_NOT_FOUND_RESP_FORMAT = {
37+
"jsonrpc": "2.0",
38+
"error": {
39+
"code": -32601,
40+
"message": "the method eth_getTransactionByHash does not exist/is not "
41+
"available",
42+
},
43+
}
44+
ETH_TESTER_METHOD_NOT_FOUND_RESP_FORMAT = {
45+
"error": "the method eth_getTransactionByHash does not exist/is not available",
46+
}
3547

3648

3749
def raise_contract_logic_error(response):
@@ -105,6 +117,20 @@ def raise_contract_logic_error(response):
105117
raise_transaction_not_found,
106118
TransactionNotFound,
107119
),
120+
(
121+
METHOD_NOT_FOUND_RESP_FORMAT,
122+
(),
123+
identity,
124+
identity,
125+
MethodUnavailable,
126+
),
127+
(
128+
ETH_TESTER_METHOD_NOT_FOUND_RESP_FORMAT,
129+
(),
130+
identity,
131+
identity,
132+
ValueError,
133+
),
108134
],
109135
)
110136
def test_formatted_response_raises_errors(

web3/exceptions.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,11 @@ class BadResponseFormat(Web3Exception):
287287
"""
288288

289289
pass
290+
291+
292+
class MethodUnavailable(Web3Exception):
293+
"""
294+
Raised when the method is not available on the node
295+
"""
296+
297+
pass

web3/manager.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
)
3535
from web3.exceptions import (
3636
BadResponseFormat,
37+
MethodUnavailable,
3738
)
3839
from web3.middleware import (
3940
abi_middleware,
@@ -188,6 +189,13 @@ def formatted_response(
188189
) -> Any:
189190
if "error" in response:
190191
apply_error_formatters(error_formatters, response)
192+
193+
# guard against eth-tester case - eth-tester returns a string
194+
# with no code, so can't parse what the error is.
195+
if isinstance(response["error"], dict):
196+
resp_code = response["error"].get("code")
197+
if resp_code == -32601:
198+
raise MethodUnavailable(response["error"])
191199
raise ValueError(response["error"])
192200
# NULL_RESPONSES includes None, so return False here as the default
193201
# so we don't apply the null_result_formatters if there is no 'result' key

0 commit comments

Comments
 (0)