We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Better error message on failed encoding
* Version: 4.1.0

### What was wrong?

A field of type `HexBytes` slipped through the pythonic middleware and the web3 provider tried to encode it with json. The only error message was:

> TypeError: Object of type 'HexBytes' is not JSON serializable


### How can it be fixed?

Catch type errors in:

```
~/web3/providers/base.py in encode_rpc_request(self, method, params)
     65             "method": method,
---> 66             "params": params or [],
     67             "id": next(self.request_counter),
     68         }))
     69
```
In case of a `TypeError`, inspect `params` and raise another `TypeError` saying which parameter index was failing to json encode, and (if applicable) which key in the `dict` at that index.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `web3/utils/encoding.py`
Content:
```
1 # String encodings and numeric representations
2 import re
3 
4 from eth_utils import (
5     add_0x_prefix,
6     big_endian_to_int,
7     decode_hex,
8     encode_hex,
9     int_to_big_endian,
10     is_boolean,
11     is_bytes,
12     is_hex,
13     is_integer,
14     remove_0x_prefix,
15     to_hex,
16 )
17 
18 from web3.utils.abi import (
19     is_address_type,
20     is_array_type,
21     is_bool_type,
22     is_bytes_type,
23     is_int_type,
24     is_string_type,
25     is_uint_type,
26     size_of_type,
27     sub_type_of_array_type,
28 )
29 from web3.utils.toolz import (
30     curry,
31 )
32 from web3.utils.validation import (
33     assert_one_val,
34     validate_abi_type,
35     validate_abi_value,
36 )
37 
38 
39 def hex_encode_abi_type(abi_type, value, force_size=None):
40     """
41     Encodes value into a hex string in format of abi_type
42     """
43     validate_abi_type(abi_type)
44     validate_abi_value(abi_type, value)
45 
46     data_size = force_size or size_of_type(abi_type)
47     if is_array_type(abi_type):
48         sub_type = sub_type_of_array_type(abi_type)
49         return "".join([remove_0x_prefix(hex_encode_abi_type(sub_type, v, 256)) for v in value])
50     elif is_bool_type(abi_type):
51         return to_hex_with_size(value, data_size)
52     elif is_uint_type(abi_type):
53         return to_hex_with_size(value, data_size)
54     elif is_int_type(abi_type):
55         return to_hex_twos_compliment(value, data_size)
56     elif is_address_type(abi_type):
57         return pad_hex(value, data_size)
58     elif is_bytes_type(abi_type):
59         if is_bytes(value):
60             return encode_hex(value)
61         else:
62             return value
63     elif is_string_type(abi_type):
64         return to_hex(text=value)
65     else:
66         raise ValueError(
67             "Unsupported ABI type: {0}".format(abi_type)
68         )
69 
70 
71 def to_hex_twos_compliment(value, bit_size):
72     """
73     Converts integer value to twos compliment hex representation with given bit_size
74     """
75     if value >= 0:
76         return to_hex_with_size(value, bit_size)
77 
78     value = (1 << bit_size) + value
79     hex_value = hex(value)
80     hex_value = hex_value.rstrip("L")
81     return hex_value
82 
83 
84 def to_hex_with_size(value, bit_size):
85     """
86     Converts a value to hex with given bit_size:
87     """
88     return pad_hex(to_hex(value), bit_size)
89 
90 
91 def pad_hex(value, bit_size):
92     """
93     Pads a hex string up to the given bit_size
94     """
95     value = remove_0x_prefix(value)
96     return add_0x_prefix(value.zfill(int(bit_size / 4)))
97 
98 
99 def trim_hex(hexstr):
100     if hexstr.startswith('0x0'):
101         hexstr = re.sub('^0x0+', '0x', hexstr)
102         if hexstr == '0x':
103             hexstr = '0x0'
104     return hexstr
105 
106 
107 def to_int(value=None, hexstr=None, text=None):
108     """
109     Converts value to it's integer representation.
110 
111     Values are converted this way:
112 
113      * value:
114        * bytes: big-endian integer
115        * bool: True => 1, False => 0
116      * hexstr: interpret hex as integer
117      * text: interpret as string of digits, like '12' => 12
118     """
119     assert_one_val(value, hexstr=hexstr, text=text)
120 
121     if hexstr is not None:
122         return int(hexstr, 16)
123     elif text is not None:
124         return int(text)
125     elif isinstance(value, bytes):
126         return big_endian_to_int(value)
127     elif isinstance(value, str):
128         raise TypeError("Pass in strings with keyword hexstr or text")
129     else:
130         return int(value)
131 
132 
133 @curry
134 def pad_bytes(fill_with, num_bytes, unpadded):
135     return unpadded.rjust(num_bytes, fill_with)
136 
137 
138 zpad_bytes = pad_bytes(b'\0')
139 
140 
141 def to_bytes(primitive=None, hexstr=None, text=None):
142     assert_one_val(primitive, hexstr=hexstr, text=text)
143 
144     if is_boolean(primitive):
145         return b'\x01' if primitive else b'\x00'
146     elif isinstance(primitive, bytes):
147         return primitive
148     elif is_integer(primitive):
149         return to_bytes(hexstr=to_hex(primitive))
150     elif hexstr is not None:
151         if len(hexstr) % 2:
152             hexstr = '0x0' + remove_0x_prefix(hexstr)
153         return decode_hex(hexstr)
154     elif text is not None:
155         return text.encode('utf-8')
156     raise TypeError("expected an int in first arg, or keyword of hexstr or text")
157 
158 
159 def to_text(primitive=None, hexstr=None, text=None):
160     assert_one_val(primitive, hexstr=hexstr, text=text)
161 
162     if hexstr is not None:
163         return to_bytes(hexstr=hexstr).decode('utf-8')
164     elif text is not None:
165         return text
166     elif isinstance(primitive, str):
167         return to_text(hexstr=primitive)
168     elif isinstance(primitive, bytes):
169         return primitive.decode('utf-8')
170     elif is_integer(primitive):
171         byte_encoding = int_to_big_endian(primitive)
172         return to_text(byte_encoding)
173     raise TypeError("Expected an int, bytes or hexstr.")
174 
175 
176 @curry
177 def text_if_str(to_type, text_or_primitive):
178     '''
179     Convert to a type, assuming that strings can be only unicode text (not a hexstr)
180 
181     @param to_type is a function that takes the arguments (primitive, hexstr=hexstr, text=text),
182         eg~ to_bytes, to_text, to_hex, to_int, etc
183     @param hexstr_or_primitive in bytes, str, or int.
184     '''
185     if isinstance(text_or_primitive, str):
186         (primitive, text) = (None, text_or_primitive)
187     else:
188         (primitive, text) = (text_or_primitive, None)
189     return to_type(primitive, text=text)
190 
191 
192 @curry
193 def hexstr_if_str(to_type, hexstr_or_primitive):
194     '''
195     Convert to a type, assuming that strings can be only hexstr (not unicode text)
196 
197     @param to_type is a function that takes the arguments (primitive, hexstr=hexstr, text=text),
198         eg~ to_bytes, to_text, to_hex, to_int, etc
199     @param text_or_primitive in bytes, str, or int.
200     '''
201     if isinstance(hexstr_or_primitive, str):
202         (primitive, hexstr) = (None, hexstr_or_primitive)
203         if remove_0x_prefix(hexstr) and not is_hex(hexstr):
204             raise ValueError(
205                 "when sending a str, it must be a hex string. Got: {0!r}".format(
206                     hexstr_or_primitive,
207                 )
208             )
209     else:
210         (primitive, hexstr) = (hexstr_or_primitive, None)
211     return to_type(primitive, hexstr=hexstr)
212
```

Path: `web3/providers/__init__.py`
Content:
```
1 from .base import (  # noqa: F401
2     BaseProvider,
3 )
4 from .rpc import HTTPProvider  # noqa: F401
5 from .ipc import IPCProvider  # noqa: F401
6 from .websocket import WebsocketProvider  # noqa: F401
7 from .auto import AutoProvider  # noqa: F401
8
```

Path: `web3/providers/base.py`
Content:
```
1 import itertools
2 import json
3 
4 from eth_utils import (
5     to_bytes,
6     to_text,
7 )
8 
9 from web3.middleware import (
10     combine_middlewares,
11 )
12 
13 
14 class BaseProvider:
15     _middlewares = ()
16     _request_func_cache = (None, None)  # a tuple of (all_middlewares, request_func)
17 
18     @property
19     def middlewares(self):
20         return self._middlewares
21 
22     @middlewares.setter
23     def middlewares(self, values):
24         self._middlewares = tuple(values)
25 
26     def request_func(self, web3, outer_middlewares):
27         '''
28         @param outer_middlewares is an iterable of middlewares, ordered by first to execute
29         @returns a function that calls all the middleware and eventually self.make_request()
30         '''
31         all_middlewares = tuple(outer_middlewares) + tuple(self.middlewares)
32 
33         cache_key = self._request_func_cache[0]
34         if cache_key is None or cache_key != all_middlewares:
35             self._request_func_cache = (
36                 all_middlewares,
37                 self._generate_request_func(web3, all_middlewares)
38             )
39         return self._request_func_cache[-1]
40 
41     def _generate_request_func(self, web3, middlewares):
42         return combine_middlewares(
43             middlewares=middlewares,
44             web3=web3,
45             provider_request_fn=self.make_request,
46         )
47 
48     def make_request(self, method, params):
49         raise NotImplementedError("Providers must implement this method")
50 
51     def isConnected(self):
52         raise NotImplementedError("Providers must implement this method")
53 
54 
55 class JSONBaseProvider(BaseProvider):
56     def __init__(self):
57         self.request_counter = itertools.count()
58 
59     def decode_rpc_response(self, response):
60         return json.loads(to_text(response))
61 
62     def encode_rpc_request(self, method, params):
63         return to_bytes(text=json.dumps({
64             "jsonrpc": "2.0",
65             "method": method,
66             "params": params or [],
67             "id": next(self.request_counter),
68         }))
69 
70     def isConnected(self):
71         try:
72             response = self.make_request('web3_clientVersion', [])
73         except IOError:
74             return False
75         else:
76             assert response['jsonrpc'] == '2.0'
77             assert 'error' not in response
78             return True
79         assert False
80
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/web3/providers/__init__.py b/web3/providers/__init__.py
--- a/web3/providers/__init__.py
+++ b/web3/providers/__init__.py
@@ -1,6 +1,8 @@
 from .base import (  # noqa: F401
     BaseProvider,
+    JSONBaseProvider,
 )
+
 from .rpc import HTTPProvider  # noqa: F401
 from .ipc import IPCProvider  # noqa: F401
 from .websocket import WebsocketProvider  # noqa: F401
diff --git a/web3/providers/base.py b/web3/providers/base.py
--- a/web3/providers/base.py
+++ b/web3/providers/base.py
@@ -1,5 +1,4 @@
 import itertools
-import json
 
 from eth_utils import (
     to_bytes,
@@ -9,6 +8,9 @@
 from web3.middleware import (
     combine_middlewares,
 )
+from web3.utils.encoding import (
+    FriendlyJsonSerde,
+)
 
 
 class BaseProvider:
@@ -57,15 +59,18 @@
         self.request_counter = itertools.count()
 
     def decode_rpc_response(self, response):
-        return json.loads(to_text(response))
+        text_response = to_text(response)
+        return FriendlyJsonSerde().json_decode(text_response)
 
     def encode_rpc_request(self, method, params):
-        return to_bytes(text=json.dumps({
+        rpc_dict = {
             "jsonrpc": "2.0",
             "method": method,
             "params": params or [],
             "id": next(self.request_counter),
-        }))
+        }
+        encoded = FriendlyJsonSerde().json_encode(rpc_dict)
+        return to_bytes(text=encoded)
 
     def isConnected(self):
         try:
diff --git a/web3/utils/encoding.py b/web3/utils/encoding.py
--- a/web3/utils/encoding.py
+++ b/web3/utils/encoding.py
@@ -1,4 +1,5 @@
 # String encodings and numeric representations
+import json
 import re
 
 from eth_utils import (
@@ -11,6 +12,7 @@
     is_bytes,
     is_hex,
     is_integer,
+    is_list_like,
     remove_0x_prefix,
     to_hex,
 )
@@ -209,3 +211,54 @@
     else:
         (primitive, hexstr) = (hexstr_or_primitive, None)
     return to_type(primitive, hexstr=hexstr)
+
+
+class FriendlyJsonSerde:
+    '''
+    Friendly JSON serializer & deserializer
+
+    When encoding or decoding fails, this class collects
+    information on which fields failed, to show more
+    helpful information in the raised error messages.
+    '''
+    def _json_mapping_errors(self, mapping):
+        for key, val in mapping.items():
+            try:
+                self._friendly_json_encode(val)
+            except TypeError as exc:
+                yield "%r: because (%s)" % (key, exc)
+
+    def _json_list_errors(self, iterable):
+        for index, element in enumerate(iterable):
+            try:
+                self._friendly_json_encode(element)
+            except TypeError as exc:
+                yield "%d: because (%s)" % (index, exc)
+
+    def _friendly_json_encode(self, obj):
+        try:
+            encoded = json.dumps(obj)
+            return encoded
+        except TypeError as full_exception:
+            if hasattr(obj, 'items'):
+                item_errors = '; '.join(self._json_mapping_errors(obj))
+                raise TypeError("dict had unencodable value at keys: {{{}}}".format(item_errors))
+            elif is_list_like(obj):
+                element_errors = '; '.join(self._json_list_errors(obj))
+                raise TypeError("list had unencodable value at index: [{}]".format(element_errors))
+            else:
+                raise full_exception
+
+    def json_decode(self, json_str):
+        try:
+            decoded = json.loads(json_str)
+            return decoded
+        except json.decoder.JSONDecodeError as exc:
+            err_msg = 'Could not decode {} because of {}.'.format(repr(json_str), exc)
+            raise ValueError(err_msg)
+
+    def json_encode(self, obj):
+        try:
+            return self._friendly_json_encode(obj)
+        except TypeError as exc:
+            raise TypeError("Could not encode to JSON: {}".format(exc))

{"golden_diff": "diff --git a/web3/providers/__init__.py b/web3/providers/__init__.py\n--- a/web3/providers/__init__.py\n+++ b/web3/providers/__init__.py\n@@ -1,6 +1,8 @@\n from .base import (  # noqa: F401\n     BaseProvider,\n+    JSONBaseProvider,\n )\n+\n from .rpc import HTTPProvider  # noqa: F401\n from .ipc import IPCProvider  # noqa: F401\n from .websocket import WebsocketProvider  # noqa: F401\ndiff --git a/web3/providers/base.py b/web3/providers/base.py\n--- a/web3/providers/base.py\n+++ b/web3/providers/base.py\n@@ -1,5 +1,4 @@\n import itertools\n-import json\n \n from eth_utils import (\n     to_bytes,\n@@ -9,6 +8,9 @@\n from web3.middleware import (\n     combine_middlewares,\n )\n+from web3.utils.encoding import (\n+    FriendlyJsonSerde,\n+)\n \n \n class BaseProvider:\n@@ -57,15 +59,18 @@\n         self.request_counter = itertools.count()\n \n     def decode_rpc_response(self, response):\n-        return json.loads(to_text(response))\n+        text_response = to_text(response)\n+        return FriendlyJsonSerde().json_decode(text_response)\n \n     def encode_rpc_request(self, method, params):\n-        return to_bytes(text=json.dumps({\n+        rpc_dict = {\n             \"jsonrpc\": \"2.0\",\n             \"method\": method,\n             \"params\": params or [],\n             \"id\": next(self.request_counter),\n-        }))\n+        }\n+        encoded = FriendlyJsonSerde().json_encode(rpc_dict)\n+        return to_bytes(text=encoded)\n \n     def isConnected(self):\n         try:\ndiff --git a/web3/utils/encoding.py b/web3/utils/encoding.py\n--- a/web3/utils/encoding.py\n+++ b/web3/utils/encoding.py\n@@ -1,4 +1,5 @@\n # String encodings and numeric representations\n+import json\n import re\n \n from eth_utils import (\n@@ -11,6 +12,7 @@\n     is_bytes,\n     is_hex,\n     is_integer,\n+    is_list_like,\n     remove_0x_prefix,\n     to_hex,\n )\n@@ -209,3 +211,54 @@\n     else:\n         (primitive, hexstr) = (hexstr_or_primitive, None)\n     return to_type(primitive, hexstr=hexstr)\n+\n+\n+class FriendlyJsonSerde:\n+    '''\n+    Friendly JSON serializer & deserializer\n+\n+    When encoding or decoding fails, this class collects\n+    information on which fields failed, to show more\n+    helpful information in the raised error messages.\n+    '''\n+    def _json_mapping_errors(self, mapping):\n+        for key, val in mapping.items():\n+            try:\n+                self._friendly_json_encode(val)\n+            except TypeError as exc:\n+                yield \"%r: because (%s)\" % (key, exc)\n+\n+    def _json_list_errors(self, iterable):\n+        for index, element in enumerate(iterable):\n+            try:\n+                self._friendly_json_encode(element)\n+            except TypeError as exc:\n+                yield \"%d: because (%s)\" % (index, exc)\n+\n+    def _friendly_json_encode(self, obj):\n+        try:\n+            encoded = json.dumps(obj)\n+            return encoded\n+        except TypeError as full_exception:\n+            if hasattr(obj, 'items'):\n+                item_errors = '; '.join(self._json_mapping_errors(obj))\n+                raise TypeError(\"dict had unencodable value at keys: {{{}}}\".format(item_errors))\n+            elif is_list_like(obj):\n+                element_errors = '; '.join(self._json_list_errors(obj))\n+                raise TypeError(\"list had unencodable value at index: [{}]\".format(element_errors))\n+            else:\n+                raise full_exception\n+\n+    def json_decode(self, json_str):\n+        try:\n+            decoded = json.loads(json_str)\n+            return decoded\n+        except json.decoder.JSONDecodeError as exc:\n+            err_msg = 'Could not decode {} because of {}.'.format(repr(json_str), exc)\n+            raise ValueError(err_msg)\n+\n+    def json_encode(self, obj):\n+        try:\n+            return self._friendly_json_encode(obj)\n+        except TypeError as exc:\n+            raise TypeError(\"Could not encode to JSON: {}\".format(exc))\n", "issue": "Better error message on failed encoding\n* Version: 4.1.0\r\n\r\n### What was wrong?\r\n\r\nA field of type `HexBytes` slipped through the pythonic middleware and the web3 provider tried to encode it with json. The only error message was:\r\n\r\n> TypeError: Object of type 'HexBytes' is not JSON serializable\r\n\r\n\r\n### How can it be fixed?\r\n\r\nCatch type errors in:\r\n\r\n```\r\n~/web3/providers/base.py in encode_rpc_request(self, method, params)\r\n     65             \"method\": method,\r\n---> 66             \"params\": params or [],\r\n     67             \"id\": next(self.request_counter),\r\n     68         }))\r\n     69\r\n```\r\nIn case of a `TypeError`, inspect `params` and raise another `TypeError` saying which parameter index was failing to json encode, and (if applicable) which key in the `dict` at that index.\n", "before_files": [{"content": "# String encodings and numeric representations\nimport re\n\nfrom eth_utils import (\n    add_0x_prefix,\n    big_endian_to_int,\n    decode_hex,\n    encode_hex,\n    int_to_big_endian,\n    is_boolean,\n    is_bytes,\n    is_hex,\n    is_integer,\n    remove_0x_prefix,\n    to_hex,\n)\n\nfrom web3.utils.abi import (\n    is_address_type,\n    is_array_type,\n    is_bool_type,\n    is_bytes_type,\n    is_int_type,\n    is_string_type,\n    is_uint_type,\n    size_of_type,\n    sub_type_of_array_type,\n)\nfrom web3.utils.toolz import (\n    curry,\n)\nfrom web3.utils.validation import (\n    assert_one_val,\n    validate_abi_type,\n    validate_abi_value,\n)\n\n\ndef hex_encode_abi_type(abi_type, value, force_size=None):\n    \"\"\"\n    Encodes value into a hex string in format of abi_type\n    \"\"\"\n    validate_abi_type(abi_type)\n    validate_abi_value(abi_type, value)\n\n    data_size = force_size or size_of_type(abi_type)\n    if is_array_type(abi_type):\n        sub_type = sub_type_of_array_type(abi_type)\n        return \"\".join([remove_0x_prefix(hex_encode_abi_type(sub_type, v, 256)) for v in value])\n    elif is_bool_type(abi_type):\n        return to_hex_with_size(value, data_size)\n    elif is_uint_type(abi_type):\n        return to_hex_with_size(value, data_size)\n    elif is_int_type(abi_type):\n        return to_hex_twos_compliment(value, data_size)\n    elif is_address_type(abi_type):\n        return pad_hex(value, data_size)\n    elif is_bytes_type(abi_type):\n        if is_bytes(value):\n            return encode_hex(value)\n        else:\n            return value\n    elif is_string_type(abi_type):\n        return to_hex(text=value)\n    else:\n        raise ValueError(\n            \"Unsupported ABI type: {0}\".format(abi_type)\n        )\n\n\ndef to_hex_twos_compliment(value, bit_size):\n    \"\"\"\n    Converts integer value to twos compliment hex representation with given bit_size\n    \"\"\"\n    if value >= 0:\n        return to_hex_with_size(value, bit_size)\n\n    value = (1 << bit_size) + value\n    hex_value = hex(value)\n    hex_value = hex_value.rstrip(\"L\")\n    return hex_value\n\n\ndef to_hex_with_size(value, bit_size):\n    \"\"\"\n    Converts a value to hex with given bit_size:\n    \"\"\"\n    return pad_hex(to_hex(value), bit_size)\n\n\ndef pad_hex(value, bit_size):\n    \"\"\"\n    Pads a hex string up to the given bit_size\n    \"\"\"\n    value = remove_0x_prefix(value)\n    return add_0x_prefix(value.zfill(int(bit_size / 4)))\n\n\ndef trim_hex(hexstr):\n    if hexstr.startswith('0x0'):\n        hexstr = re.sub('^0x0+', '0x', hexstr)\n        if hexstr == '0x':\n            hexstr = '0x0'\n    return hexstr\n\n\ndef to_int(value=None, hexstr=None, text=None):\n    \"\"\"\n    Converts value to it's integer representation.\n\n    Values are converted this way:\n\n     * value:\n       * bytes: big-endian integer\n       * bool: True => 1, False => 0\n     * hexstr: interpret hex as integer\n     * text: interpret as string of digits, like '12' => 12\n    \"\"\"\n    assert_one_val(value, hexstr=hexstr, text=text)\n\n    if hexstr is not None:\n        return int(hexstr, 16)\n    elif text is not None:\n        return int(text)\n    elif isinstance(value, bytes):\n        return big_endian_to_int(value)\n    elif isinstance(value, str):\n        raise TypeError(\"Pass in strings with keyword hexstr or text\")\n    else:\n        return int(value)\n\n\n@curry\ndef pad_bytes(fill_with, num_bytes, unpadded):\n    return unpadded.rjust(num_bytes, fill_with)\n\n\nzpad_bytes = pad_bytes(b'\\0')\n\n\ndef to_bytes(primitive=None, hexstr=None, text=None):\n    assert_one_val(primitive, hexstr=hexstr, text=text)\n\n    if is_boolean(primitive):\n        return b'\\x01' if primitive else b'\\x00'\n    elif isinstance(primitive, bytes):\n        return primitive\n    elif is_integer(primitive):\n        return to_bytes(hexstr=to_hex(primitive))\n    elif hexstr is not None:\n        if len(hexstr) % 2:\n            hexstr = '0x0' + remove_0x_prefix(hexstr)\n        return decode_hex(hexstr)\n    elif text is not None:\n        return text.encode('utf-8')\n    raise TypeError(\"expected an int in first arg, or keyword of hexstr or text\")\n\n\ndef to_text(primitive=None, hexstr=None, text=None):\n    assert_one_val(primitive, hexstr=hexstr, text=text)\n\n    if hexstr is not None:\n        return to_bytes(hexstr=hexstr).decode('utf-8')\n    elif text is not None:\n        return text\n    elif isinstance(primitive, str):\n        return to_text(hexstr=primitive)\n    elif isinstance(primitive, bytes):\n        return primitive.decode('utf-8')\n    elif is_integer(primitive):\n        byte_encoding = int_to_big_endian(primitive)\n        return to_text(byte_encoding)\n    raise TypeError(\"Expected an int, bytes or hexstr.\")\n\n\n@curry\ndef text_if_str(to_type, text_or_primitive):\n    '''\n    Convert to a type, assuming that strings can be only unicode text (not a hexstr)\n\n    @param to_type is a function that takes the arguments (primitive, hexstr=hexstr, text=text),\n        eg~ to_bytes, to_text, to_hex, to_int, etc\n    @param hexstr_or_primitive in bytes, str, or int.\n    '''\n    if isinstance(text_or_primitive, str):\n        (primitive, text) = (None, text_or_primitive)\n    else:\n        (primitive, text) = (text_or_primitive, None)\n    return to_type(primitive, text=text)\n\n\n@curry\ndef hexstr_if_str(to_type, hexstr_or_primitive):\n    '''\n    Convert to a type, assuming that strings can be only hexstr (not unicode text)\n\n    @param to_type is a function that takes the arguments (primitive, hexstr=hexstr, text=text),\n        eg~ to_bytes, to_text, to_hex, to_int, etc\n    @param text_or_primitive in bytes, str, or int.\n    '''\n    if isinstance(hexstr_or_primitive, str):\n        (primitive, hexstr) = (None, hexstr_or_primitive)\n        if remove_0x_prefix(hexstr) and not is_hex(hexstr):\n            raise ValueError(\n                \"when sending a str, it must be a hex string. Got: {0!r}\".format(\n                    hexstr_or_primitive,\n                )\n            )\n    else:\n        (primitive, hexstr) = (hexstr_or_primitive, None)\n    return to_type(primitive, hexstr=hexstr)\n", "path": "web3/utils/encoding.py"}, {"content": "from .base import (  # noqa: F401\n    BaseProvider,\n)\nfrom .rpc import HTTPProvider  # noqa: F401\nfrom .ipc import IPCProvider  # noqa: F401\nfrom .websocket import WebsocketProvider  # noqa: F401\nfrom .auto import AutoProvider  # noqa: F401\n", "path": "web3/providers/__init__.py"}, {"content": "import itertools\nimport json\n\nfrom eth_utils import (\n    to_bytes,\n    to_text,\n)\n\nfrom web3.middleware import (\n    combine_middlewares,\n)\n\n\nclass BaseProvider:\n    _middlewares = ()\n    _request_func_cache = (None, None)  # a tuple of (all_middlewares, request_func)\n\n    @property\n    def middlewares(self):\n        return self._middlewares\n\n    @middlewares.setter\n    def middlewares(self, values):\n        self._middlewares = tuple(values)\n\n    def request_func(self, web3, outer_middlewares):\n        '''\n        @param outer_middlewares is an iterable of middlewares, ordered by first to execute\n        @returns a function that calls all the middleware and eventually self.make_request()\n        '''\n        all_middlewares = tuple(outer_middlewares) + tuple(self.middlewares)\n\n        cache_key = self._request_func_cache[0]\n        if cache_key is None or cache_key != all_middlewares:\n            self._request_func_cache = (\n                all_middlewares,\n                self._generate_request_func(web3, all_middlewares)\n            )\n        return self._request_func_cache[-1]\n\n    def _generate_request_func(self, web3, middlewares):\n        return combine_middlewares(\n            middlewares=middlewares,\n            web3=web3,\n            provider_request_fn=self.make_request,\n        )\n\n    def make_request(self, method, params):\n        raise NotImplementedError(\"Providers must implement this method\")\n\n    def isConnected(self):\n        raise NotImplementedError(\"Providers must implement this method\")\n\n\nclass JSONBaseProvider(BaseProvider):\n    def __init__(self):\n        self.request_counter = itertools.count()\n\n    def decode_rpc_response(self, response):\n        return json.loads(to_text(response))\n\n    def encode_rpc_request(self, method, params):\n        return to_bytes(text=json.dumps({\n            \"jsonrpc\": \"2.0\",\n            \"method\": method,\n            \"params\": params or [],\n            \"id\": next(self.request_counter),\n        }))\n\n    def isConnected(self):\n        try:\n            response = self.make_request('web3_clientVersion', [])\n        except IOError:\n            return False\n        else:\n            assert response['jsonrpc'] == '2.0'\n            assert 'error' not in response\n            return True\n        assert False\n", "path": "web3/providers/base.py"}], "after_files": [{"content": "# String encodings and numeric representations\nimport json\nimport re\n\nfrom eth_utils import (\n    add_0x_prefix,\n    big_endian_to_int,\n    decode_hex,\n    encode_hex,\n    int_to_big_endian,\n    is_boolean,\n    is_bytes,\n    is_hex,\n    is_integer,\n    is_list_like,\n    remove_0x_prefix,\n    to_hex,\n)\n\nfrom web3.utils.abi import (\n    is_address_type,\n    is_array_type,\n    is_bool_type,\n    is_bytes_type,\n    is_int_type,\n    is_string_type,\n    is_uint_type,\n    size_of_type,\n    sub_type_of_array_type,\n)\nfrom web3.utils.toolz import (\n    curry,\n)\nfrom web3.utils.validation import (\n    assert_one_val,\n    validate_abi_type,\n    validate_abi_value,\n)\n\n\ndef hex_encode_abi_type(abi_type, value, force_size=None):\n    \"\"\"\n    Encodes value into a hex string in format of abi_type\n    \"\"\"\n    validate_abi_type(abi_type)\n    validate_abi_value(abi_type, value)\n\n    data_size = force_size or size_of_type(abi_type)\n    if is_array_type(abi_type):\n        sub_type = sub_type_of_array_type(abi_type)\n        return \"\".join([remove_0x_prefix(hex_encode_abi_type(sub_type, v, 256)) for v in value])\n    elif is_bool_type(abi_type):\n        return to_hex_with_size(value, data_size)\n    elif is_uint_type(abi_type):\n        return to_hex_with_size(value, data_size)\n    elif is_int_type(abi_type):\n        return to_hex_twos_compliment(value, data_size)\n    elif is_address_type(abi_type):\n        return pad_hex(value, data_size)\n    elif is_bytes_type(abi_type):\n        if is_bytes(value):\n            return encode_hex(value)\n        else:\n            return value\n    elif is_string_type(abi_type):\n        return to_hex(text=value)\n    else:\n        raise ValueError(\n            \"Unsupported ABI type: {0}\".format(abi_type)\n        )\n\n\ndef to_hex_twos_compliment(value, bit_size):\n    \"\"\"\n    Converts integer value to twos compliment hex representation with given bit_size\n    \"\"\"\n    if value >= 0:\n        return to_hex_with_size(value, bit_size)\n\n    value = (1 << bit_size) + value\n    hex_value = hex(value)\n    hex_value = hex_value.rstrip(\"L\")\n    return hex_value\n\n\ndef to_hex_with_size(value, bit_size):\n    \"\"\"\n    Converts a value to hex with given bit_size:\n    \"\"\"\n    return pad_hex(to_hex(value), bit_size)\n\n\ndef pad_hex(value, bit_size):\n    \"\"\"\n    Pads a hex string up to the given bit_size\n    \"\"\"\n    value = remove_0x_prefix(value)\n    return add_0x_prefix(value.zfill(int(bit_size / 4)))\n\n\ndef trim_hex(hexstr):\n    if hexstr.startswith('0x0'):\n        hexstr = re.sub('^0x0+', '0x', hexstr)\n        if hexstr == '0x':\n            hexstr = '0x0'\n    return hexstr\n\n\ndef to_int(value=None, hexstr=None, text=None):\n    \"\"\"\n    Converts value to it's integer representation.\n\n    Values are converted this way:\n\n     * value:\n       * bytes: big-endian integer\n       * bool: True => 1, False => 0\n     * hexstr: interpret hex as integer\n     * text: interpret as string of digits, like '12' => 12\n    \"\"\"\n    assert_one_val(value, hexstr=hexstr, text=text)\n\n    if hexstr is not None:\n        return int(hexstr, 16)\n    elif text is not None:\n        return int(text)\n    elif isinstance(value, bytes):\n        return big_endian_to_int(value)\n    elif isinstance(value, str):\n        raise TypeError(\"Pass in strings with keyword hexstr or text\")\n    else:\n        return int(value)\n\n\n@curry\ndef pad_bytes(fill_with, num_bytes, unpadded):\n    return unpadded.rjust(num_bytes, fill_with)\n\n\nzpad_bytes = pad_bytes(b'\\0')\n\n\ndef to_bytes(primitive=None, hexstr=None, text=None):\n    assert_one_val(primitive, hexstr=hexstr, text=text)\n\n    if is_boolean(primitive):\n        return b'\\x01' if primitive else b'\\x00'\n    elif isinstance(primitive, bytes):\n        return primitive\n    elif is_integer(primitive):\n        return to_bytes(hexstr=to_hex(primitive))\n    elif hexstr is not None:\n        if len(hexstr) % 2:\n            hexstr = '0x0' + remove_0x_prefix(hexstr)\n        return decode_hex(hexstr)\n    elif text is not None:\n        return text.encode('utf-8')\n    raise TypeError(\"expected an int in first arg, or keyword of hexstr or text\")\n\n\ndef to_text(primitive=None, hexstr=None, text=None):\n    assert_one_val(primitive, hexstr=hexstr, text=text)\n\n    if hexstr is not None:\n        return to_bytes(hexstr=hexstr).decode('utf-8')\n    elif text is not None:\n        return text\n    elif isinstance(primitive, str):\n        return to_text(hexstr=primitive)\n    elif isinstance(primitive, bytes):\n        return primitive.decode('utf-8')\n    elif is_integer(primitive):\n        byte_encoding = int_to_big_endian(primitive)\n        return to_text(byte_encoding)\n    raise TypeError(\"Expected an int, bytes or hexstr.\")\n\n\n@curry\ndef text_if_str(to_type, text_or_primitive):\n    '''\n    Convert to a type, assuming that strings can be only unicode text (not a hexstr)\n\n    @param to_type is a function that takes the arguments (primitive, hexstr=hexstr, text=text),\n        eg~ to_bytes, to_text, to_hex, to_int, etc\n    @param hexstr_or_primitive in bytes, str, or int.\n    '''\n    if isinstance(text_or_primitive, str):\n        (primitive, text) = (None, text_or_primitive)\n    else:\n        (primitive, text) = (text_or_primitive, None)\n    return to_type(primitive, text=text)\n\n\n@curry\ndef hexstr_if_str(to_type, hexstr_or_primitive):\n    '''\n    Convert to a type, assuming that strings can be only hexstr (not unicode text)\n\n    @param to_type is a function that takes the arguments (primitive, hexstr=hexstr, text=text),\n        eg~ to_bytes, to_text, to_hex, to_int, etc\n    @param text_or_primitive in bytes, str, or int.\n    '''\n    if isinstance(hexstr_or_primitive, str):\n        (primitive, hexstr) = (None, hexstr_or_primitive)\n        if remove_0x_prefix(hexstr) and not is_hex(hexstr):\n            raise ValueError(\n                \"when sending a str, it must be a hex string. Got: {0!r}\".format(\n                    hexstr_or_primitive,\n                )\n            )\n    else:\n        (primitive, hexstr) = (hexstr_or_primitive, None)\n    return to_type(primitive, hexstr=hexstr)\n\n\nclass FriendlyJsonSerde:\n    '''\n    Friendly JSON serializer & deserializer\n\n    When encoding or decoding fails, this class collects\n    information on which fields failed, to show more\n    helpful information in the raised error messages.\n    '''\n    def _json_mapping_errors(self, mapping):\n        for key, val in mapping.items():\n            try:\n                self._friendly_json_encode(val)\n            except TypeError as exc:\n                yield \"%r: because (%s)\" % (key, exc)\n\n    def _json_list_errors(self, iterable):\n        for index, element in enumerate(iterable):\n            try:\n                self._friendly_json_encode(element)\n            except TypeError as exc:\n                yield \"%d: because (%s)\" % (index, exc)\n\n    def _friendly_json_encode(self, obj):\n        try:\n            encoded = json.dumps(obj)\n            return encoded\n        except TypeError as full_exception:\n            if hasattr(obj, 'items'):\n                item_errors = '; '.join(self._json_mapping_errors(obj))\n                raise TypeError(\"dict had unencodable value at keys: {{{}}}\".format(item_errors))\n            elif is_list_like(obj):\n                element_errors = '; '.join(self._json_list_errors(obj))\n                raise TypeError(\"list had unencodable value at index: [{}]\".format(element_errors))\n            else:\n                raise full_exception\n\n    def json_decode(self, json_str):\n        try:\n            decoded = json.loads(json_str)\n            return decoded\n        except json.decoder.JSONDecodeError as exc:\n            err_msg = 'Could not decode {} because of {}.'.format(repr(json_str), exc)\n            raise ValueError(err_msg)\n\n    def json_encode(self, obj):\n        try:\n            return self._friendly_json_encode(obj)\n        except TypeError as exc:\n            raise TypeError(\"Could not encode to JSON: {}\".format(exc))\n", "path": "web3/utils/encoding.py"}, {"content": "from .base import (  # noqa: F401\n    BaseProvider,\n    JSONBaseProvider,\n)\n\nfrom .rpc import HTTPProvider  # noqa: F401\nfrom .ipc import IPCProvider  # noqa: F401\nfrom .websocket import WebsocketProvider  # noqa: F401\nfrom .auto import AutoProvider  # noqa: F401\n", "path": "web3/providers/__init__.py"}, {"content": "import itertools\n\nfrom eth_utils import (\n    to_bytes,\n    to_text,\n)\n\nfrom web3.middleware import (\n    combine_middlewares,\n)\nfrom web3.utils.encoding import (\n    FriendlyJsonSerde,\n)\n\n\nclass BaseProvider:\n    _middlewares = ()\n    _request_func_cache = (None, None)  # a tuple of (all_middlewares, request_func)\n\n    @property\n    def middlewares(self):\n        return self._middlewares\n\n    @middlewares.setter\n    def middlewares(self, values):\n        self._middlewares = tuple(values)\n\n    def request_func(self, web3, outer_middlewares):\n        '''\n        @param outer_middlewares is an iterable of middlewares, ordered by first to execute\n        @returns a function that calls all the middleware and eventually self.make_request()\n        '''\n        all_middlewares = tuple(outer_middlewares) + tuple(self.middlewares)\n\n        cache_key = self._request_func_cache[0]\n        if cache_key is None or cache_key != all_middlewares:\n            self._request_func_cache = (\n                all_middlewares,\n                self._generate_request_func(web3, all_middlewares)\n            )\n        return self._request_func_cache[-1]\n\n    def _generate_request_func(self, web3, middlewares):\n        return combine_middlewares(\n            middlewares=middlewares,\n            web3=web3,\n            provider_request_fn=self.make_request,\n        )\n\n    def make_request(self, method, params):\n        raise NotImplementedError(\"Providers must implement this method\")\n\n    def isConnected(self):\n        raise NotImplementedError(\"Providers must implement this method\")\n\n\nclass JSONBaseProvider(BaseProvider):\n    def __init__(self):\n        self.request_counter = itertools.count()\n\n    def decode_rpc_response(self, response):\n        text_response = to_text(response)\n        return FriendlyJsonSerde().json_decode(text_response)\n\n    def encode_rpc_request(self, method, params):\n        rpc_dict = {\n            \"jsonrpc\": \"2.0\",\n            \"method\": method,\n            \"params\": params or [],\n            \"id\": next(self.request_counter),\n        }\n        encoded = FriendlyJsonSerde().json_encode(rpc_dict)\n        return to_bytes(text=encoded)\n\n    def isConnected(self):\n        try:\n            response = self.make_request('web3_clientVersion', [])\n        except IOError:\n            return False\n        else:\n            assert response['jsonrpc'] == '2.0'\n            assert 'error' not in response\n            return True\n        assert False\n", "path": "web3/providers/base.py"}]}