faster-eth-utils 5.3.20__cp314-cp314-win32.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.
Potentially problematic release.
This version of faster-eth-utils might be problematic. Click here for more details.
- faster_eth_utils/__init__.py +144 -0
- faster_eth_utils/__json/eth_networks.json +1 -0
- faster_eth_utils/__main__.py +5 -0
- faster_eth_utils/abi.cp314-win32.pyd +0 -0
- faster_eth_utils/abi.py +847 -0
- faster_eth_utils/address.cp314-win32.pyd +0 -0
- faster_eth_utils/address.py +145 -0
- faster_eth_utils/applicators.cp314-win32.pyd +0 -0
- faster_eth_utils/applicators.py +209 -0
- faster_eth_utils/conversions.cp314-win32.pyd +0 -0
- faster_eth_utils/conversions.py +191 -0
- faster_eth_utils/crypto.cp314-win32.pyd +0 -0
- faster_eth_utils/crypto.py +21 -0
- faster_eth_utils/currency.cp314-win32.pyd +0 -0
- faster_eth_utils/currency.py +141 -0
- faster_eth_utils/curried/__init__.py +306 -0
- faster_eth_utils/debug.cp314-win32.pyd +0 -0
- faster_eth_utils/debug.py +20 -0
- faster_eth_utils/decorators.cp314-win32.pyd +0 -0
- faster_eth_utils/decorators.py +119 -0
- faster_eth_utils/encoding.cp314-win32.pyd +0 -0
- faster_eth_utils/encoding.py +6 -0
- faster_eth_utils/exceptions.cp314-win32.pyd +0 -0
- faster_eth_utils/exceptions.py +11 -0
- faster_eth_utils/functional.cp314-win32.pyd +0 -0
- faster_eth_utils/functional.py +89 -0
- faster_eth_utils/hexadecimal.cp314-win32.pyd +0 -0
- faster_eth_utils/hexadecimal.py +80 -0
- faster_eth_utils/humanize.cp314-win32.pyd +0 -0
- faster_eth_utils/humanize.py +201 -0
- faster_eth_utils/logging.py +146 -0
- faster_eth_utils/module_loading.cp314-win32.pyd +0 -0
- faster_eth_utils/module_loading.py +31 -0
- faster_eth_utils/network.cp314-win32.pyd +0 -0
- faster_eth_utils/network.py +92 -0
- faster_eth_utils/numeric.cp314-win32.pyd +0 -0
- faster_eth_utils/numeric.py +43 -0
- faster_eth_utils/py.typed +0 -0
- faster_eth_utils/pydantic.py +101 -0
- faster_eth_utils/toolz.cp314-win32.pyd +0 -0
- faster_eth_utils/toolz.py +84 -0
- faster_eth_utils/types.cp314-win32.pyd +0 -0
- faster_eth_utils/types.py +68 -0
- faster_eth_utils/typing/__init__.py +18 -0
- faster_eth_utils/typing/misc.py +14 -0
- faster_eth_utils/units.cp314-win32.pyd +0 -0
- faster_eth_utils/units.py +31 -0
- faster_eth_utils-5.3.20.dist-info/METADATA +193 -0
- faster_eth_utils-5.3.20.dist-info/RECORD +53 -0
- faster_eth_utils-5.3.20.dist-info/WHEEL +5 -0
- faster_eth_utils-5.3.20.dist-info/licenses/LICENSE +21 -0
- faster_eth_utils-5.3.20.dist-info/top_level.txt +3 -0
- faster_eth_utils__mypyc.cp314-win32.pyd +0 -0
|
Binary file
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import (
|
|
3
|
+
Any,
|
|
4
|
+
Final,
|
|
5
|
+
Union,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
import cchecksum
|
|
9
|
+
from eth_typing import (
|
|
10
|
+
Address,
|
|
11
|
+
AnyAddress,
|
|
12
|
+
ChecksumAddress,
|
|
13
|
+
HexAddress,
|
|
14
|
+
HexStr,
|
|
15
|
+
)
|
|
16
|
+
from typing_extensions import (
|
|
17
|
+
TypeGuard,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from .conversions import (
|
|
21
|
+
hexstr_if_str,
|
|
22
|
+
to_hex,
|
|
23
|
+
)
|
|
24
|
+
from .crypto import (
|
|
25
|
+
keccak,
|
|
26
|
+
)
|
|
27
|
+
from .hexadecimal import (
|
|
28
|
+
add_0x_prefix,
|
|
29
|
+
decode_hex,
|
|
30
|
+
encode_hex,
|
|
31
|
+
remove_0x_prefix,
|
|
32
|
+
)
|
|
33
|
+
from .types import (
|
|
34
|
+
is_bytes,
|
|
35
|
+
is_text,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
_HEX_ADDRESS_REGEXP: Final = re.compile("(0x)?[0-9a-f]{40}", re.IGNORECASE | re.ASCII)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
to_checksum_address: Final = cchecksum.to_checksum_address
|
|
42
|
+
"""
|
|
43
|
+
Makes a checksum address given a supported format.
|
|
44
|
+
We use the `cchecksum` implementation for max speed.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def is_hex_address(value: Any) -> TypeGuard[HexAddress]:
|
|
49
|
+
"""
|
|
50
|
+
Checks if the given string of text type is an address in hexadecimal encoded form.
|
|
51
|
+
"""
|
|
52
|
+
if not is_text(value):
|
|
53
|
+
return False
|
|
54
|
+
return _HEX_ADDRESS_REGEXP.fullmatch(value) is not None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def is_binary_address(value: Any) -> TypeGuard[bytes]:
|
|
58
|
+
"""
|
|
59
|
+
Checks if the given string is an address in raw bytes form.
|
|
60
|
+
"""
|
|
61
|
+
if not is_bytes(value):
|
|
62
|
+
return False
|
|
63
|
+
elif len(value) != 20:
|
|
64
|
+
return False
|
|
65
|
+
else:
|
|
66
|
+
return True
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def is_address(value: Any) -> bool:
|
|
70
|
+
"""
|
|
71
|
+
Is the given string an address in any of the known formats?
|
|
72
|
+
"""
|
|
73
|
+
if is_hex_address(value) or is_binary_address(value):
|
|
74
|
+
return True
|
|
75
|
+
|
|
76
|
+
return False
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def to_normalized_address(value: Union[AnyAddress, str, bytes]) -> HexAddress:
|
|
80
|
+
"""
|
|
81
|
+
Converts an address to its normalized hexadecimal representation.
|
|
82
|
+
"""
|
|
83
|
+
try:
|
|
84
|
+
hex_address = hexstr_if_str(to_hex, value).lower()
|
|
85
|
+
except AttributeError:
|
|
86
|
+
raise TypeError(f"Value must be any string, instead got type {type(value)}")
|
|
87
|
+
if is_address(hex_address):
|
|
88
|
+
return HexAddress(HexStr(hex_address))
|
|
89
|
+
else:
|
|
90
|
+
raise ValueError(
|
|
91
|
+
f"Unknown format {repr(value)}, attempted to normalize to "
|
|
92
|
+
f"{repr(hex_address)}"
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def is_normalized_address(value: Any) -> TypeGuard[HexAddress]:
|
|
97
|
+
"""
|
|
98
|
+
Returns whether the provided value is an address in its normalized form.
|
|
99
|
+
"""
|
|
100
|
+
return is_address(value) and value == to_normalized_address(value)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def to_canonical_address(address: Union[AnyAddress, str, bytes]) -> Address:
|
|
104
|
+
"""
|
|
105
|
+
Convert a valid address to its canonical form (20-length bytes).
|
|
106
|
+
"""
|
|
107
|
+
return Address(decode_hex(to_normalized_address(address)))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def is_canonical_address(address: Any) -> TypeGuard[Address]:
|
|
111
|
+
"""
|
|
112
|
+
Returns `True` if the `value` is an address in its canonical form.
|
|
113
|
+
"""
|
|
114
|
+
return is_binary_address(address) and address == to_canonical_address(address)
|
|
115
|
+
8
|
|
116
|
+
|
|
117
|
+
def is_same_address(
|
|
118
|
+
left: Union[AnyAddress, str, bytes], right: Union[AnyAddress, str, bytes]
|
|
119
|
+
) -> bool:
|
|
120
|
+
"""
|
|
121
|
+
Checks if both addresses are same or not.
|
|
122
|
+
"""
|
|
123
|
+
if not is_address(left) or not is_address(right):
|
|
124
|
+
raise ValueError("Both values must be valid addresses")
|
|
125
|
+
else:
|
|
126
|
+
return to_normalized_address(left) == to_normalized_address(right)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def is_checksum_address(value: Any) -> TypeGuard[ChecksumAddress]:
|
|
130
|
+
if not is_hex_address(value):
|
|
131
|
+
return False
|
|
132
|
+
return value == to_checksum_address(value)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _is_checksum_formatted(value: Any) -> bool:
|
|
136
|
+
unprefixed_value = remove_0x_prefix(value)
|
|
137
|
+
return (
|
|
138
|
+
not unprefixed_value.islower()
|
|
139
|
+
and not unprefixed_value.isupper()
|
|
140
|
+
and not unprefixed_value.isnumeric()
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def is_checksum_formatted_address(value: Any) -> bool:
|
|
145
|
+
return is_hex_address(value) and _is_checksum_formatted(value)
|
|
Binary file
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from typing import (
|
|
3
|
+
TYPE_CHECKING,
|
|
4
|
+
Any,
|
|
5
|
+
Callable,
|
|
6
|
+
Dict,
|
|
7
|
+
Generator,
|
|
8
|
+
List,
|
|
9
|
+
Mapping,
|
|
10
|
+
Sequence,
|
|
11
|
+
Tuple,
|
|
12
|
+
TypeVar,
|
|
13
|
+
Union,
|
|
14
|
+
cast,
|
|
15
|
+
overload,
|
|
16
|
+
)
|
|
17
|
+
import warnings
|
|
18
|
+
|
|
19
|
+
from typing_extensions import (
|
|
20
|
+
TypeGuard,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
from .decorators import (
|
|
24
|
+
return_arg_type,
|
|
25
|
+
)
|
|
26
|
+
from .pydantic import (
|
|
27
|
+
CamelModel,
|
|
28
|
+
)
|
|
29
|
+
from .toolz import (
|
|
30
|
+
compose,
|
|
31
|
+
curry,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
if sys.version_info >= (3, 9):
|
|
36
|
+
from _typeshed import SupportsBool
|
|
37
|
+
# We have to sacrifice a little bit of specificity on dinosaur Python3.8
|
|
38
|
+
else:
|
|
39
|
+
SupportsBool = Any
|
|
40
|
+
|
|
41
|
+
TArg = TypeVar("TArg")
|
|
42
|
+
TReturn = TypeVar("TReturn")
|
|
43
|
+
TOther = TypeVar("TOther")
|
|
44
|
+
|
|
45
|
+
Formatters = Callable[[List[Any]], List[Any]]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@return_arg_type(2)
|
|
49
|
+
def apply_formatter_at_index(
|
|
50
|
+
formatter: Callable[[TArg], TReturn],
|
|
51
|
+
at_index: int,
|
|
52
|
+
value: Sequence[Union[TArg, TOther]],
|
|
53
|
+
) -> Generator[Union[TOther, TReturn], None, None]:
|
|
54
|
+
try:
|
|
55
|
+
item = value[at_index]
|
|
56
|
+
except IndexError:
|
|
57
|
+
raise IndexError(
|
|
58
|
+
f"Not enough values in iterable to apply formatter. Got: {len(value)}. "
|
|
59
|
+
f"Need: {at_index + 1}"
|
|
60
|
+
) from None
|
|
61
|
+
|
|
62
|
+
yield from cast(Sequence[TOther], value[:at_index])
|
|
63
|
+
yield formatter(cast(TArg, item))
|
|
64
|
+
yield from cast(Sequence[TOther], value[at_index + 1 :])
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def combine_argument_formatters(*formatters: Callable[..., Any]) -> Formatters:
|
|
68
|
+
warnings.warn(
|
|
69
|
+
DeprecationWarning(
|
|
70
|
+
"combine_argument_formatters(formatter1, formatter2)([item1, item2])"
|
|
71
|
+
"has been deprecated and will be removed in a subsequent major version "
|
|
72
|
+
"release of the eth-utils library. Update your calls to use "
|
|
73
|
+
"apply_formatters_to_sequence([formatter1, formatter2], [item1, item2]) "
|
|
74
|
+
"instead."
|
|
75
|
+
),
|
|
76
|
+
stacklevel=2,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
_formatter_at_index = curry(apply_formatter_at_index)
|
|
80
|
+
return compose( # type: ignore [no-any-return]
|
|
81
|
+
*(
|
|
82
|
+
_formatter_at_index(formatter, index)
|
|
83
|
+
for index, formatter in enumerate(formatters)
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@return_arg_type(1)
|
|
89
|
+
def apply_formatters_to_sequence(
|
|
90
|
+
formatters: List[Callable[[Any], TReturn]], sequence: Sequence[Any]
|
|
91
|
+
) -> Generator[TReturn, None, None]:
|
|
92
|
+
num_formatters = len(formatters)
|
|
93
|
+
num_items = len(sequence)
|
|
94
|
+
if num_formatters == num_items:
|
|
95
|
+
for formatter, item in zip(formatters, sequence):
|
|
96
|
+
yield formatter(item)
|
|
97
|
+
elif num_formatters > num_items:
|
|
98
|
+
raise IndexError(
|
|
99
|
+
f"Too many formatters for sequence: {num_formatters} formatters for "
|
|
100
|
+
f"{sequence!r}"
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
raise IndexError(
|
|
104
|
+
f"Too few formatters for sequence: {num_formatters} formatters for "
|
|
105
|
+
f"{sequence!r}"
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@overload
|
|
110
|
+
def apply_formatter_if(
|
|
111
|
+
condition: Callable[[TArg], TypeGuard[TOther]],
|
|
112
|
+
formatter: Callable[[TOther], TReturn],
|
|
113
|
+
value: TArg,
|
|
114
|
+
) -> Union[TArg, TReturn]: ...
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@overload
|
|
118
|
+
def apply_formatter_if(
|
|
119
|
+
condition: Callable[[TArg], bool], formatter: Callable[[TArg], TReturn], value: TArg
|
|
120
|
+
) -> Union[TArg, TReturn]: ...
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def apply_formatter_if( # type: ignore [misc]
|
|
124
|
+
condition: Union[Callable[[TArg], TypeGuard[TOther]], Callable[[TArg], bool]],
|
|
125
|
+
formatter: Union[Callable[[TOther], TReturn], Callable[[TArg], TReturn]],
|
|
126
|
+
value: TArg,
|
|
127
|
+
) -> Union[TArg, TReturn]:
|
|
128
|
+
if condition(value):
|
|
129
|
+
return formatter(value) # type: ignore [arg-type]
|
|
130
|
+
else:
|
|
131
|
+
return value
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def apply_formatters_to_dict(
|
|
135
|
+
formatters: Dict[Any, Any],
|
|
136
|
+
value: Union[Dict[Any, Any], CamelModel],
|
|
137
|
+
unaliased: bool = False,
|
|
138
|
+
) -> Dict[Any, Any]:
|
|
139
|
+
"""
|
|
140
|
+
Apply formatters to a dictionary of values. If the value is a pydantic model,
|
|
141
|
+
it will be serialized to a dictionary first, taking into account the
|
|
142
|
+
``unaliased`` parameter.
|
|
143
|
+
|
|
144
|
+
:param formatters: The formatters to apply to the dictionary.
|
|
145
|
+
:param value: The dictionary-like object to apply the formatters to.
|
|
146
|
+
:param unaliased: If the model is a ``CamelModel``, whether to turn off
|
|
147
|
+
serialization by alias (camelCase).
|
|
148
|
+
:return: A generator that yields the formatted key-value pairs.
|
|
149
|
+
"""
|
|
150
|
+
if isinstance(value, CamelModel):
|
|
151
|
+
value = value.model_dump(by_alias=not unaliased)
|
|
152
|
+
|
|
153
|
+
def get_value(key: Any, val: Any) -> Any:
|
|
154
|
+
if key not in formatters:
|
|
155
|
+
return val
|
|
156
|
+
try:
|
|
157
|
+
return formatters[key](val)
|
|
158
|
+
except ValueError as exc:
|
|
159
|
+
raise ValueError(
|
|
160
|
+
f"Could not format invalid value {val!r} as field {key!r}"
|
|
161
|
+
) from exc
|
|
162
|
+
except TypeError as exc:
|
|
163
|
+
raise TypeError(
|
|
164
|
+
f"Could not format invalid type {val!r} as field {key!r}"
|
|
165
|
+
) from exc
|
|
166
|
+
|
|
167
|
+
return {key: get_value(key, val) for key, val in value.items()}
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@return_arg_type(1)
|
|
171
|
+
def apply_formatter_to_array(
|
|
172
|
+
formatter: Callable[[TArg], TReturn], value: Sequence[TArg]
|
|
173
|
+
) -> Generator[TReturn, None, None]:
|
|
174
|
+
for item in value:
|
|
175
|
+
yield formatter(item)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def apply_one_of_formatters(
|
|
179
|
+
formatter_condition_pairs: Tuple[
|
|
180
|
+
Tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]], ...
|
|
181
|
+
],
|
|
182
|
+
value: TArg,
|
|
183
|
+
) -> TReturn:
|
|
184
|
+
for condition, formatter in formatter_condition_pairs:
|
|
185
|
+
if condition(value):
|
|
186
|
+
return formatter(value)
|
|
187
|
+
else:
|
|
188
|
+
raise ValueError(
|
|
189
|
+
"The provided value did not satisfy any of the formatter conditions"
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def apply_key_map(
|
|
194
|
+
key_mappings: Dict[Any, Any], value: Mapping[Any, Any]
|
|
195
|
+
) -> Dict[Any, Any]:
|
|
196
|
+
key_conflicts = (
|
|
197
|
+
set(value.keys())
|
|
198
|
+
.difference(key_mappings.keys())
|
|
199
|
+
.intersection(v for k, v in key_mappings.items() if v in value)
|
|
200
|
+
)
|
|
201
|
+
if key_conflicts:
|
|
202
|
+
raise KeyError(
|
|
203
|
+
f"Could not apply key map due to conflicting key(s): {key_conflicts}"
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
def get_key(key: Any) -> Any:
|
|
207
|
+
return key_mappings[key] if key in key_mappings else key
|
|
208
|
+
|
|
209
|
+
return {get_key(key): item for key, item in value.items()}
|
|
Binary file
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Callable,
|
|
3
|
+
Optional,
|
|
4
|
+
TypeVar,
|
|
5
|
+
Union,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
from eth_typing import (
|
|
9
|
+
HexStr,
|
|
10
|
+
Primitives,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from .encoding import (
|
|
14
|
+
big_endian_to_int,
|
|
15
|
+
int_to_big_endian,
|
|
16
|
+
)
|
|
17
|
+
from .hexadecimal import (
|
|
18
|
+
add_0x_prefix,
|
|
19
|
+
decode_hex,
|
|
20
|
+
encode_hex,
|
|
21
|
+
is_hexstr,
|
|
22
|
+
remove_0x_prefix,
|
|
23
|
+
)
|
|
24
|
+
from .types import (
|
|
25
|
+
is_string,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
T = TypeVar("T")
|
|
29
|
+
|
|
30
|
+
BytesLike = Union[Primitives, bytearray, memoryview]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def to_hex(
|
|
34
|
+
primitive: Optional[BytesLike] = None,
|
|
35
|
+
hexstr: Optional[HexStr] = None,
|
|
36
|
+
text: Optional[str] = None,
|
|
37
|
+
) -> HexStr:
|
|
38
|
+
"""
|
|
39
|
+
Auto converts any supported value into its hex representation.
|
|
40
|
+
Trims leading zeros, as defined in:
|
|
41
|
+
https://github.com/ethereum/wiki/wiki/JSON-RPC#hex-value-encoding
|
|
42
|
+
"""
|
|
43
|
+
if hexstr is not None:
|
|
44
|
+
return add_0x_prefix(HexStr(hexstr.lower()))
|
|
45
|
+
|
|
46
|
+
if text is not None:
|
|
47
|
+
return encode_hex(text.encode("utf-8"))
|
|
48
|
+
|
|
49
|
+
if isinstance(primitive, bool):
|
|
50
|
+
return HexStr("0x1") if primitive else HexStr("0x0")
|
|
51
|
+
|
|
52
|
+
if isinstance(primitive, (bytes, bytearray)):
|
|
53
|
+
return encode_hex(primitive)
|
|
54
|
+
|
|
55
|
+
if isinstance(primitive, memoryview):
|
|
56
|
+
return encode_hex(bytes(primitive))
|
|
57
|
+
|
|
58
|
+
elif is_string(primitive):
|
|
59
|
+
raise TypeError(
|
|
60
|
+
"Unsupported type: The primitive argument must be one of: bytes,"
|
|
61
|
+
"bytearray, int or bool and not str"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
if isinstance(primitive, int):
|
|
65
|
+
return HexStr(hex(primitive))
|
|
66
|
+
|
|
67
|
+
raise TypeError(
|
|
68
|
+
f"Unsupported type: '{repr(type(primitive))}'. Must be one of: bool, str, "
|
|
69
|
+
"bytes, bytearray or int."
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def to_int(
|
|
74
|
+
primitive: Optional[BytesLike] = None,
|
|
75
|
+
hexstr: Optional[HexStr] = None,
|
|
76
|
+
text: Optional[str] = None,
|
|
77
|
+
) -> int:
|
|
78
|
+
"""
|
|
79
|
+
Converts value to its integer representation.
|
|
80
|
+
Values are converted this way:
|
|
81
|
+
|
|
82
|
+
* primitive:
|
|
83
|
+
|
|
84
|
+
* bytes, bytearray, memoryview: big-endian integer
|
|
85
|
+
* bool: True => 1, False => 0
|
|
86
|
+
* int: unchanged
|
|
87
|
+
* hexstr: interpret hex as integer
|
|
88
|
+
* text: interpret as string of digits, like '12' => 12
|
|
89
|
+
"""
|
|
90
|
+
if hexstr is not None:
|
|
91
|
+
return int(hexstr, 16)
|
|
92
|
+
elif text is not None:
|
|
93
|
+
return int(text)
|
|
94
|
+
elif isinstance(primitive, (bytes, bytearray)):
|
|
95
|
+
return big_endian_to_int(primitive)
|
|
96
|
+
elif isinstance(primitive, memoryview):
|
|
97
|
+
return big_endian_to_int(bytes(primitive))
|
|
98
|
+
elif isinstance(primitive, str):
|
|
99
|
+
raise TypeError("Pass in strings with keyword hexstr or text")
|
|
100
|
+
elif isinstance(primitive, (int, bool)):
|
|
101
|
+
return int(primitive)
|
|
102
|
+
else:
|
|
103
|
+
raise TypeError(
|
|
104
|
+
"Invalid type. Expected one of int/bool/str/bytes/bytearray. Got "
|
|
105
|
+
f"{type(primitive)}"
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def to_bytes(
|
|
110
|
+
primitive: Optional[BytesLike] = None,
|
|
111
|
+
hexstr: Optional[HexStr] = None,
|
|
112
|
+
text: Optional[str] = None,
|
|
113
|
+
) -> bytes:
|
|
114
|
+
if isinstance(primitive, bool):
|
|
115
|
+
return b"\x01" if primitive else b"\x00"
|
|
116
|
+
elif isinstance(primitive, (bytearray, memoryview)):
|
|
117
|
+
return bytes(primitive)
|
|
118
|
+
elif isinstance(primitive, bytes):
|
|
119
|
+
return primitive
|
|
120
|
+
elif isinstance(primitive, int):
|
|
121
|
+
return to_bytes(hexstr=to_hex(primitive))
|
|
122
|
+
elif hexstr is not None:
|
|
123
|
+
if len(hexstr) % 2:
|
|
124
|
+
hexstr = "0x0" + remove_0x_prefix(hexstr) # type: ignore [assignment]
|
|
125
|
+
return decode_hex(hexstr)
|
|
126
|
+
elif text is not None:
|
|
127
|
+
return text.encode("utf-8")
|
|
128
|
+
raise TypeError(
|
|
129
|
+
"expected a bool, int, byte or bytearray in first arg, "
|
|
130
|
+
"or keyword of hexstr or text"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def to_text(
|
|
135
|
+
primitive: Optional[BytesLike] = None,
|
|
136
|
+
hexstr: Optional[HexStr] = None,
|
|
137
|
+
text: Optional[str] = None,
|
|
138
|
+
) -> str:
|
|
139
|
+
if hexstr is not None:
|
|
140
|
+
return to_bytes(hexstr=hexstr).decode("utf-8")
|
|
141
|
+
elif text is not None:
|
|
142
|
+
return text
|
|
143
|
+
elif isinstance(primitive, str):
|
|
144
|
+
return to_text(hexstr=primitive)
|
|
145
|
+
elif isinstance(primitive, (bytes, bytearray)):
|
|
146
|
+
return primitive.decode("utf-8")
|
|
147
|
+
elif isinstance(primitive, memoryview):
|
|
148
|
+
return bytes(primitive).decode("utf-8")
|
|
149
|
+
elif isinstance(primitive, int):
|
|
150
|
+
byte_encoding = int_to_big_endian(primitive)
|
|
151
|
+
return to_text(byte_encoding)
|
|
152
|
+
raise TypeError("Expected an int, bytes, bytearray or hexstr.")
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def text_if_str(
|
|
156
|
+
to_type: Callable[..., T], text_or_primitive: Union[bytes, int, str]
|
|
157
|
+
) -> T:
|
|
158
|
+
"""
|
|
159
|
+
Convert to a type, assuming that strings can be only unicode text (not a hexstr).
|
|
160
|
+
|
|
161
|
+
:param to_type function: takes the arguments (primitive, hexstr=hexstr, text=text),
|
|
162
|
+
eg~ to_bytes, to_text, to_hex, to_int, etc
|
|
163
|
+
:param text_or_primitive bytes, str, int: value to convert
|
|
164
|
+
"""
|
|
165
|
+
if isinstance(text_or_primitive, str):
|
|
166
|
+
return to_type(text=text_or_primitive)
|
|
167
|
+
else:
|
|
168
|
+
return to_type(text_or_primitive)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def hexstr_if_str(
|
|
172
|
+
to_type: Callable[..., T], hexstr_or_primitive: Union[bytes, int, str]
|
|
173
|
+
) -> T:
|
|
174
|
+
"""
|
|
175
|
+
Convert to a type, assuming that strings can be only hexstr (not unicode text).
|
|
176
|
+
|
|
177
|
+
:param to_type function: takes the arguments (primitive, hexstr=hexstr, text=text),
|
|
178
|
+
eg~ to_bytes, to_text, to_hex, to_int, etc
|
|
179
|
+
:param hexstr_or_primitive bytes, str, int: value to convert
|
|
180
|
+
"""
|
|
181
|
+
if isinstance(hexstr_or_primitive, str):
|
|
182
|
+
if remove_0x_prefix(HexStr(hexstr_or_primitive)) and not is_hexstr(
|
|
183
|
+
hexstr_or_primitive
|
|
184
|
+
):
|
|
185
|
+
raise ValueError(
|
|
186
|
+
"when sending a str, it must be a hex string. "
|
|
187
|
+
f"Got: {repr(hexstr_or_primitive)}"
|
|
188
|
+
)
|
|
189
|
+
return to_type(hexstr=hexstr_or_primitive)
|
|
190
|
+
else:
|
|
191
|
+
return to_type(hexstr_or_primitive)
|
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Optional,
|
|
3
|
+
Union,
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
from eth_hash.auto import (
|
|
7
|
+
keccak as keccak_256,
|
|
8
|
+
)
|
|
9
|
+
from eth_typing import HexStr
|
|
10
|
+
|
|
11
|
+
from .conversions import (
|
|
12
|
+
to_bytes,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def keccak(
|
|
17
|
+
primitive: Optional[Union[bytes, int, bool]] = None,
|
|
18
|
+
hexstr: Optional[HexStr] = None,
|
|
19
|
+
text: Optional[str] = None,
|
|
20
|
+
) -> bytes:
|
|
21
|
+
return bytes(keccak_256(to_bytes(primitive, hexstr, text)))
|
|
Binary file
|