faster-eth-utils 4.1.7__cp314-cp314t-win_amd64.whl → 5.3.22__cp314-cp314t-win_amd64.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 +19 -1
- faster_eth_utils/abi.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/abi.py +834 -34
- faster_eth_utils/address.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/address.py +19 -43
- faster_eth_utils/applicators.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/applicators.py +109 -64
- faster_eth_utils/conversions.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/conversions.py +36 -29
- faster_eth_utils/crypto.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/crypto.py +3 -8
- faster_eth_utils/currency.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/currency.py +55 -21
- faster_eth_utils/curried/__init__.py +91 -67
- faster_eth_utils/debug.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/decorators.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/decorators.py +65 -29
- faster_eth_utils/encoding.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/encoding.py +1 -1
- faster_eth_utils/exceptions.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/exceptions.py +8 -1
- faster_eth_utils/functional.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/functional.py +10 -12
- faster_eth_utils/hexadecimal.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/hexadecimal.py +19 -16
- faster_eth_utils/humanize.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/humanize.py +35 -23
- faster_eth_utils/logging.py +54 -61
- faster_eth_utils/module_loading.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/network.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/network.py +2 -3
- faster_eth_utils/numeric.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/pydantic.py +103 -0
- faster_eth_utils/toolz.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/types.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils/types.py +20 -17
- faster_eth_utils/units.cp314t-win_amd64.pyd +0 -0
- {faster_eth_utils-4.1.7.dist-info → faster_eth_utils-5.3.22.dist-info}/METADATA +59 -17
- faster_eth_utils-5.3.22.dist-info/RECORD +53 -0
- {faster_eth_utils-4.1.7.dist-info → faster_eth_utils-5.3.22.dist-info}/licenses/LICENSE +1 -1
- faster_eth_utils-5.3.22.dist-info/top_level.txt +3 -0
- faster_eth_utils__mypyc.cp314t-win_amd64.pyd +0 -0
- 99c07adba6ff961eaf3e__mypyc.cp314t-win_amd64.pyd +0 -0
- faster_eth_utils-4.1.7.dist-info/RECORD +0 -52
- faster_eth_utils-4.1.7.dist-info/top_level.txt +0 -3
- {faster_eth_utils-4.1.7.dist-info → faster_eth_utils-5.3.22.dist-info}/WHEEL +0 -0
|
Binary file
|
faster_eth_utils/address.py
CHANGED
|
@@ -2,10 +2,10 @@ import re
|
|
|
2
2
|
from typing import (
|
|
3
3
|
Any,
|
|
4
4
|
Final,
|
|
5
|
-
|
|
6
|
-
cast,
|
|
5
|
+
TypeGuard,
|
|
7
6
|
)
|
|
8
7
|
|
|
8
|
+
import cchecksum
|
|
9
9
|
from eth_typing import (
|
|
10
10
|
Address,
|
|
11
11
|
AnyAddress,
|
|
@@ -13,21 +13,13 @@ from eth_typing import (
|
|
|
13
13
|
HexAddress,
|
|
14
14
|
HexStr,
|
|
15
15
|
)
|
|
16
|
-
from typing_extensions import (
|
|
17
|
-
TypeGuard,
|
|
18
|
-
)
|
|
19
16
|
|
|
20
17
|
from .conversions import (
|
|
21
18
|
hexstr_if_str,
|
|
22
19
|
to_hex,
|
|
23
20
|
)
|
|
24
|
-
from .crypto import (
|
|
25
|
-
keccak,
|
|
26
|
-
)
|
|
27
21
|
from .hexadecimal import (
|
|
28
|
-
add_0x_prefix,
|
|
29
22
|
decode_hex,
|
|
30
|
-
encode_hex,
|
|
31
23
|
remove_0x_prefix,
|
|
32
24
|
)
|
|
33
25
|
from .types import (
|
|
@@ -38,6 +30,13 @@ from .types import (
|
|
|
38
30
|
_HEX_ADDRESS_REGEXP: Final = re.compile("(0x)?[0-9a-f]{40}", re.IGNORECASE | re.ASCII)
|
|
39
31
|
|
|
40
32
|
|
|
33
|
+
to_checksum_address: Final = cchecksum.to_checksum_address
|
|
34
|
+
"""
|
|
35
|
+
Makes a checksum address given a supported format.
|
|
36
|
+
We use the `cchecksum` implementation for max speed.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
|
|
41
40
|
def is_hex_address(value: Any) -> TypeGuard[HexAddress]:
|
|
42
41
|
"""
|
|
43
42
|
Checks if the given string of text type is an address in hexadecimal encoded form.
|
|
@@ -69,7 +68,7 @@ def is_address(value: Any) -> bool:
|
|
|
69
68
|
return False
|
|
70
69
|
|
|
71
70
|
|
|
72
|
-
def to_normalized_address(value:
|
|
71
|
+
def to_normalized_address(value: AnyAddress | str | bytes) -> HexAddress:
|
|
73
72
|
"""
|
|
74
73
|
Converts an address to its normalized hexadecimal representation.
|
|
75
74
|
"""
|
|
@@ -90,14 +89,10 @@ def is_normalized_address(value: Any) -> TypeGuard[HexAddress]:
|
|
|
90
89
|
"""
|
|
91
90
|
Returns whether the provided value is an address in its normalized form.
|
|
92
91
|
"""
|
|
93
|
-
|
|
94
|
-
return False
|
|
95
|
-
else:
|
|
96
|
-
is_equal = value == to_normalized_address(value)
|
|
97
|
-
return cast(bool, is_equal)
|
|
92
|
+
return is_address(value) and value == to_normalized_address(value)
|
|
98
93
|
|
|
99
94
|
|
|
100
|
-
def to_canonical_address(address:
|
|
95
|
+
def to_canonical_address(address: AnyAddress | str | bytes) -> Address:
|
|
101
96
|
"""
|
|
102
97
|
Convert a valid address to its canonical form (20-length bytes).
|
|
103
98
|
"""
|
|
@@ -111,42 +106,23 @@ def is_canonical_address(address: Any) -> TypeGuard[Address]:
|
|
|
111
106
|
return is_binary_address(address) and address == to_canonical_address(address)
|
|
112
107
|
8
|
|
113
108
|
|
|
114
|
-
def is_same_address(
|
|
109
|
+
def is_same_address(
|
|
110
|
+
left: AnyAddress | str | bytes, right: AnyAddress | str | bytes
|
|
111
|
+
) -> bool:
|
|
115
112
|
"""
|
|
116
113
|
Checks if both addresses are same or not.
|
|
117
114
|
"""
|
|
118
115
|
if not is_address(left) or not is_address(right):
|
|
119
116
|
raise ValueError("Both values must be valid addresses")
|
|
120
|
-
|
|
121
|
-
return
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
def to_checksum_address(value: Union[AnyAddress, str, bytes]) -> ChecksumAddress:
|
|
125
|
-
"""
|
|
126
|
-
Makes a checksum address given a supported format.
|
|
127
|
-
"""
|
|
128
|
-
norm_address = to_normalized_address(value)
|
|
129
|
-
address_hash = encode_hex(keccak(text=remove_0x_prefix(HexStr(norm_address))))
|
|
130
|
-
|
|
131
|
-
checksum_address = add_0x_prefix(
|
|
132
|
-
HexStr(
|
|
133
|
-
"".join(
|
|
134
|
-
(
|
|
135
|
-
norm_address[i].upper()
|
|
136
|
-
if int(address_hash[i], 16) > 7
|
|
137
|
-
else norm_address[i]
|
|
138
|
-
)
|
|
139
|
-
for i in range(2, 42)
|
|
140
|
-
)
|
|
141
|
-
)
|
|
142
|
-
)
|
|
143
|
-
return ChecksumAddress(HexAddress(checksum_address))
|
|
117
|
+
if left == right:
|
|
118
|
+
return True
|
|
119
|
+
return to_normalized_address(left) == to_normalized_address(right)
|
|
144
120
|
|
|
145
121
|
|
|
146
122
|
def is_checksum_address(value: Any) -> TypeGuard[ChecksumAddress]:
|
|
147
123
|
if not is_hex_address(value):
|
|
148
124
|
return False
|
|
149
|
-
return
|
|
125
|
+
return value == to_checksum_address(value)
|
|
150
126
|
|
|
151
127
|
|
|
152
128
|
def _is_checksum_formatted(value: Any) -> bool:
|
|
Binary file
|
faster_eth_utils/applicators.py
CHANGED
|
@@ -1,41 +1,54 @@
|
|
|
1
|
+
from collections.abc import Callable, Generator, Mapping, Sequence
|
|
1
2
|
from typing import (
|
|
3
|
+
TYPE_CHECKING,
|
|
2
4
|
Any,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Tuple,
|
|
5
|
+
TypeGuard,
|
|
6
|
+
TypeVar,
|
|
7
|
+
cast,
|
|
8
|
+
overload,
|
|
8
9
|
)
|
|
10
|
+
|
|
9
11
|
import warnings
|
|
10
12
|
|
|
11
13
|
from .decorators import (
|
|
12
14
|
return_arg_type,
|
|
13
15
|
)
|
|
14
|
-
from .
|
|
15
|
-
|
|
16
|
+
from .pydantic import (
|
|
17
|
+
CamelModel,
|
|
16
18
|
)
|
|
17
19
|
from .toolz import (
|
|
18
20
|
compose,
|
|
19
21
|
curry,
|
|
20
22
|
)
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from _typeshed import SupportsBool
|
|
26
|
+
# We have to sacrifice a little bit of specificity on dinosaur Python3.8
|
|
27
|
+
|
|
28
|
+
TArg = TypeVar("TArg")
|
|
29
|
+
TReturn = TypeVar("TReturn")
|
|
30
|
+
TOther = TypeVar("TOther")
|
|
31
|
+
|
|
32
|
+
Formatters = Callable[[list[Any]], list[Any]]
|
|
23
33
|
|
|
24
34
|
|
|
25
35
|
@return_arg_type(2)
|
|
26
36
|
def apply_formatter_at_index(
|
|
27
|
-
formatter: Callable[
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
formatter: Callable[[TArg], TReturn],
|
|
38
|
+
at_index: int,
|
|
39
|
+
value: Sequence[TArg | TOther],
|
|
40
|
+
) -> Generator[TOther | TReturn, None, None]:
|
|
41
|
+
try:
|
|
42
|
+
item = value[at_index]
|
|
43
|
+
except IndexError:
|
|
30
44
|
raise IndexError(
|
|
31
45
|
f"Not enough values in iterable to apply formatter. Got: {len(value)}. "
|
|
32
46
|
f"Need: {at_index + 1}"
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
yield item
|
|
47
|
+
) from None
|
|
48
|
+
|
|
49
|
+
yield from cast(Sequence[TOther], value[:at_index])
|
|
50
|
+
yield formatter(cast(TArg, item))
|
|
51
|
+
yield from cast(Sequence[TOther], value[at_index + 1 :])
|
|
39
52
|
|
|
40
53
|
|
|
41
54
|
def combine_argument_formatters(*formatters: Callable[..., Any]) -> Formatters:
|
|
@@ -51,7 +64,7 @@ def combine_argument_formatters(*formatters: Callable[..., Any]) -> Formatters:
|
|
|
51
64
|
)
|
|
52
65
|
|
|
53
66
|
_formatter_at_index = curry(apply_formatter_at_index)
|
|
54
|
-
return compose( # type: ignore
|
|
67
|
+
return compose( # type: ignore [no-any-return]
|
|
55
68
|
*(
|
|
56
69
|
_formatter_at_index(formatter, index)
|
|
57
70
|
for index, formatter in enumerate(formatters)
|
|
@@ -61,66 +74,100 @@ def combine_argument_formatters(*formatters: Callable[..., Any]) -> Formatters:
|
|
|
61
74
|
|
|
62
75
|
@return_arg_type(1)
|
|
63
76
|
def apply_formatters_to_sequence(
|
|
64
|
-
formatters:
|
|
65
|
-
) -> Generator[
|
|
66
|
-
|
|
77
|
+
formatters: list[Callable[[Any], TReturn]], sequence: Sequence[Any]
|
|
78
|
+
) -> Generator[TReturn, None, None]:
|
|
79
|
+
num_formatters = len(formatters)
|
|
80
|
+
num_items = len(sequence)
|
|
81
|
+
if num_formatters == num_items:
|
|
82
|
+
for formatter, item in zip(formatters, sequence):
|
|
83
|
+
yield formatter(item)
|
|
84
|
+
elif num_formatters > num_items:
|
|
67
85
|
raise IndexError(
|
|
68
|
-
f"Too many formatters for sequence: {
|
|
69
|
-
f"{
|
|
86
|
+
f"Too many formatters for sequence: {num_formatters} formatters for "
|
|
87
|
+
f"{sequence!r}"
|
|
70
88
|
)
|
|
71
|
-
|
|
89
|
+
else:
|
|
72
90
|
raise IndexError(
|
|
73
|
-
f"Too few formatters for sequence: {
|
|
74
|
-
f"{
|
|
91
|
+
f"Too few formatters for sequence: {num_formatters} formatters for "
|
|
92
|
+
f"{sequence!r}"
|
|
75
93
|
)
|
|
76
|
-
else:
|
|
77
|
-
for formatter, item in zip(formatters, sequence):
|
|
78
|
-
yield formatter(item)
|
|
79
94
|
|
|
80
95
|
|
|
96
|
+
@overload
|
|
81
97
|
def apply_formatter_if(
|
|
82
|
-
condition: Callable[
|
|
83
|
-
|
|
98
|
+
condition: Callable[[TArg], TypeGuard[TOther]],
|
|
99
|
+
formatter: Callable[[TOther], TReturn],
|
|
100
|
+
value: TArg,
|
|
101
|
+
) -> TArg | TReturn: ...
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@overload
|
|
105
|
+
def apply_formatter_if(
|
|
106
|
+
condition: Callable[[TArg], bool], formatter: Callable[[TArg], TReturn], value: TArg
|
|
107
|
+
) -> TArg | TReturn: ...
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def apply_formatter_if( # type: ignore [misc]
|
|
111
|
+
condition: Callable[[TArg], TypeGuard[TOther]] | Callable[[TArg], bool],
|
|
112
|
+
formatter: Callable[[TOther], TReturn] | Callable[[TArg], TReturn],
|
|
113
|
+
value: TArg,
|
|
114
|
+
) -> TArg | TReturn:
|
|
84
115
|
if condition(value):
|
|
85
|
-
return formatter(value)
|
|
116
|
+
return formatter(value) # type: ignore [arg-type]
|
|
86
117
|
else:
|
|
87
118
|
return value
|
|
88
119
|
|
|
89
120
|
|
|
90
|
-
@to_dict
|
|
91
121
|
def apply_formatters_to_dict(
|
|
92
|
-
formatters:
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
122
|
+
formatters: dict[Any, Any],
|
|
123
|
+
value: dict[Any, Any] | CamelModel,
|
|
124
|
+
unaliased: bool = False,
|
|
125
|
+
) -> dict[Any, Any]:
|
|
126
|
+
"""
|
|
127
|
+
Apply formatters to a dictionary of values. If the value is a pydantic model,
|
|
128
|
+
it will be serialized to a dictionary first, taking into account the
|
|
129
|
+
``unaliased`` parameter.
|
|
130
|
+
|
|
131
|
+
:param formatters: The formatters to apply to the dictionary.
|
|
132
|
+
:param value: The dictionary-like object to apply the formatters to.
|
|
133
|
+
:param unaliased: If the model is a ``CamelModel``, whether to turn off
|
|
134
|
+
serialization by alias (camelCase).
|
|
135
|
+
:return: A generator that yields the formatted key-value pairs.
|
|
136
|
+
"""
|
|
137
|
+
if isinstance(value, CamelModel):
|
|
138
|
+
value = value.model_dump(by_alias=not unaliased)
|
|
139
|
+
|
|
140
|
+
def get_value(key: Any, val: Any) -> Any:
|
|
141
|
+
if key not in formatters:
|
|
142
|
+
return val
|
|
143
|
+
try:
|
|
144
|
+
return formatters[key](val)
|
|
145
|
+
except ValueError as exc:
|
|
146
|
+
raise ValueError(
|
|
147
|
+
f"Could not format invalid value {val!r} as field {key!r}"
|
|
148
|
+
) from exc
|
|
149
|
+
except TypeError as exc:
|
|
150
|
+
raise TypeError(
|
|
151
|
+
f"Could not format invalid type {val!r} as field {key!r}"
|
|
152
|
+
) from exc
|
|
153
|
+
|
|
154
|
+
return {key: get_value(key, val) for key, val in value.items()}
|
|
110
155
|
|
|
111
156
|
|
|
112
157
|
@return_arg_type(1)
|
|
113
158
|
def apply_formatter_to_array(
|
|
114
|
-
formatter: Callable[
|
|
115
|
-
) -> Generator[
|
|
159
|
+
formatter: Callable[[TArg], TReturn], value: Sequence[TArg]
|
|
160
|
+
) -> Generator[TReturn, None, None]:
|
|
116
161
|
for item in value:
|
|
117
162
|
yield formatter(item)
|
|
118
163
|
|
|
119
164
|
|
|
120
165
|
def apply_one_of_formatters(
|
|
121
|
-
formatter_condition_pairs:
|
|
122
|
-
|
|
123
|
-
|
|
166
|
+
formatter_condition_pairs: tuple[
|
|
167
|
+
tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]], ...
|
|
168
|
+
],
|
|
169
|
+
value: TArg,
|
|
170
|
+
) -> TReturn:
|
|
124
171
|
for condition, formatter in formatter_condition_pairs:
|
|
125
172
|
if condition(value):
|
|
126
173
|
return formatter(value)
|
|
@@ -130,10 +177,9 @@ def apply_one_of_formatters(
|
|
|
130
177
|
)
|
|
131
178
|
|
|
132
179
|
|
|
133
|
-
@to_dict
|
|
134
180
|
def apply_key_map(
|
|
135
|
-
key_mappings:
|
|
136
|
-
) ->
|
|
181
|
+
key_mappings: dict[Any, Any], value: Mapping[Any, Any]
|
|
182
|
+
) -> dict[Any, Any]:
|
|
137
183
|
key_conflicts = (
|
|
138
184
|
set(value.keys())
|
|
139
185
|
.difference(key_mappings.keys())
|
|
@@ -144,8 +190,7 @@ def apply_key_map(
|
|
|
144
190
|
f"Could not apply key map due to conflicting key(s): {key_conflicts}"
|
|
145
191
|
)
|
|
146
192
|
|
|
147
|
-
|
|
148
|
-
if key in key_mappings
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
yield key, item
|
|
193
|
+
def get_key(key: Any) -> Any:
|
|
194
|
+
return key_mappings[key] if key in key_mappings else key
|
|
195
|
+
|
|
196
|
+
return {get_key(key): item for key, item in value.items()}
|
|
Binary file
|
faster_eth_utils/conversions.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
from typing import (
|
|
2
|
-
Callable,
|
|
3
|
-
Optional,
|
|
4
2
|
TypeVar,
|
|
5
3
|
Union,
|
|
6
4
|
)
|
|
5
|
+
from collections.abc import Callable
|
|
7
6
|
|
|
8
7
|
from eth_typing import (
|
|
9
8
|
HexStr,
|
|
@@ -22,18 +21,18 @@ from .hexadecimal import (
|
|
|
22
21
|
remove_0x_prefix,
|
|
23
22
|
)
|
|
24
23
|
from .types import (
|
|
25
|
-
is_boolean,
|
|
26
|
-
is_integer,
|
|
27
24
|
is_string,
|
|
28
25
|
)
|
|
29
26
|
|
|
30
27
|
T = TypeVar("T")
|
|
31
28
|
|
|
29
|
+
BytesLike = Union[Primitives, bytearray, memoryview]
|
|
30
|
+
|
|
32
31
|
|
|
33
32
|
def to_hex(
|
|
34
|
-
primitive:
|
|
35
|
-
hexstr:
|
|
36
|
-
text:
|
|
33
|
+
primitive: BytesLike | None = None,
|
|
34
|
+
hexstr: HexStr | None = None,
|
|
35
|
+
text: str | None = None,
|
|
37
36
|
) -> HexStr:
|
|
38
37
|
"""
|
|
39
38
|
Auto converts any supported value into its hex representation.
|
|
@@ -46,18 +45,22 @@ def to_hex(
|
|
|
46
45
|
if text is not None:
|
|
47
46
|
return encode_hex(text.encode("utf-8"))
|
|
48
47
|
|
|
49
|
-
if
|
|
48
|
+
if isinstance(primitive, bool):
|
|
50
49
|
return HexStr("0x1") if primitive else HexStr("0x0")
|
|
51
50
|
|
|
52
51
|
if isinstance(primitive, (bytes, bytearray)):
|
|
53
52
|
return encode_hex(primitive)
|
|
53
|
+
|
|
54
|
+
if isinstance(primitive, memoryview):
|
|
55
|
+
return encode_hex(bytes(primitive))
|
|
56
|
+
|
|
54
57
|
elif is_string(primitive):
|
|
55
58
|
raise TypeError(
|
|
56
59
|
"Unsupported type: The primitive argument must be one of: bytes,"
|
|
57
60
|
"bytearray, int or bool and not str"
|
|
58
61
|
)
|
|
59
62
|
|
|
60
|
-
if
|
|
63
|
+
if isinstance(primitive, int):
|
|
61
64
|
return HexStr(hex(primitive))
|
|
62
65
|
|
|
63
66
|
raise TypeError(
|
|
@@ -67,9 +70,9 @@ def to_hex(
|
|
|
67
70
|
|
|
68
71
|
|
|
69
72
|
def to_int(
|
|
70
|
-
primitive:
|
|
71
|
-
hexstr:
|
|
72
|
-
text:
|
|
73
|
+
primitive: BytesLike | None = None,
|
|
74
|
+
hexstr: HexStr | None = None,
|
|
75
|
+
text: str | None = None,
|
|
73
76
|
) -> int:
|
|
74
77
|
"""
|
|
75
78
|
Converts value to its integer representation.
|
|
@@ -77,8 +80,9 @@ def to_int(
|
|
|
77
80
|
|
|
78
81
|
* primitive:
|
|
79
82
|
|
|
80
|
-
* bytes,
|
|
83
|
+
* bytes, bytearray, memoryview: big-endian integer
|
|
81
84
|
* bool: True => 1, False => 0
|
|
85
|
+
* int: unchanged
|
|
82
86
|
* hexstr: interpret hex as integer
|
|
83
87
|
* text: interpret as string of digits, like '12' => 12
|
|
84
88
|
"""
|
|
@@ -88,6 +92,8 @@ def to_int(
|
|
|
88
92
|
return int(text)
|
|
89
93
|
elif isinstance(primitive, (bytes, bytearray)):
|
|
90
94
|
return big_endian_to_int(primitive)
|
|
95
|
+
elif isinstance(primitive, memoryview):
|
|
96
|
+
return big_endian_to_int(bytes(primitive))
|
|
91
97
|
elif isinstance(primitive, str):
|
|
92
98
|
raise TypeError("Pass in strings with keyword hexstr or text")
|
|
93
99
|
elif isinstance(primitive, (int, bool)):
|
|
@@ -100,21 +106,21 @@ def to_int(
|
|
|
100
106
|
|
|
101
107
|
|
|
102
108
|
def to_bytes(
|
|
103
|
-
primitive:
|
|
104
|
-
hexstr:
|
|
105
|
-
text:
|
|
109
|
+
primitive: BytesLike | None = None,
|
|
110
|
+
hexstr: HexStr | None = None,
|
|
111
|
+
text: str | None = None,
|
|
106
112
|
) -> bytes:
|
|
107
|
-
if
|
|
113
|
+
if isinstance(primitive, bool):
|
|
108
114
|
return b"\x01" if primitive else b"\x00"
|
|
109
|
-
elif isinstance(primitive, bytearray):
|
|
115
|
+
elif isinstance(primitive, (bytearray, memoryview)):
|
|
110
116
|
return bytes(primitive)
|
|
111
117
|
elif isinstance(primitive, bytes):
|
|
112
118
|
return primitive
|
|
113
|
-
elif
|
|
114
|
-
return
|
|
119
|
+
elif isinstance(primitive, int):
|
|
120
|
+
return int_to_big_endian(primitive)
|
|
115
121
|
elif hexstr is not None:
|
|
116
122
|
if len(hexstr) % 2:
|
|
117
|
-
hexstr = "0x0
|
|
123
|
+
hexstr = HexStr(f"0x0{remove_0x_prefix(hexstr)}")
|
|
118
124
|
return decode_hex(hexstr)
|
|
119
125
|
elif text is not None:
|
|
120
126
|
return text.encode("utf-8")
|
|
@@ -125,9 +131,9 @@ def to_bytes(
|
|
|
125
131
|
|
|
126
132
|
|
|
127
133
|
def to_text(
|
|
128
|
-
primitive:
|
|
129
|
-
hexstr:
|
|
130
|
-
text:
|
|
134
|
+
primitive: BytesLike | None = None,
|
|
135
|
+
hexstr: HexStr | None = None,
|
|
136
|
+
text: str | None = None,
|
|
131
137
|
) -> str:
|
|
132
138
|
if hexstr is not None:
|
|
133
139
|
return to_bytes(hexstr=hexstr).decode("utf-8")
|
|
@@ -137,14 +143,15 @@ def to_text(
|
|
|
137
143
|
return to_text(hexstr=primitive)
|
|
138
144
|
elif isinstance(primitive, (bytes, bytearray)):
|
|
139
145
|
return primitive.decode("utf-8")
|
|
140
|
-
elif
|
|
141
|
-
|
|
142
|
-
|
|
146
|
+
elif isinstance(primitive, memoryview):
|
|
147
|
+
return bytes(primitive).decode("utf-8")
|
|
148
|
+
elif isinstance(primitive, int):
|
|
149
|
+
return int_to_big_endian(primitive).decode("utf-8")
|
|
143
150
|
raise TypeError("Expected an int, bytes, bytearray or hexstr.")
|
|
144
151
|
|
|
145
152
|
|
|
146
153
|
def text_if_str(
|
|
147
|
-
to_type: Callable[..., T], text_or_primitive:
|
|
154
|
+
to_type: Callable[..., T], text_or_primitive: bytes | int | str
|
|
148
155
|
) -> T:
|
|
149
156
|
"""
|
|
150
157
|
Convert to a type, assuming that strings can be only unicode text (not a hexstr).
|
|
@@ -160,7 +167,7 @@ def text_if_str(
|
|
|
160
167
|
|
|
161
168
|
|
|
162
169
|
def hexstr_if_str(
|
|
163
|
-
to_type: Callable[..., T], hexstr_or_primitive:
|
|
170
|
+
to_type: Callable[..., T], hexstr_or_primitive: bytes | int | str
|
|
164
171
|
) -> T:
|
|
165
172
|
"""
|
|
166
173
|
Convert to a type, assuming that strings can be only hexstr (not unicode text).
|
|
Binary file
|
faster_eth_utils/crypto.py
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
from typing import (
|
|
2
|
-
Optional,
|
|
3
|
-
Union,
|
|
4
|
-
)
|
|
5
|
-
|
|
6
1
|
from eth_hash.auto import (
|
|
7
2
|
keccak as keccak_256,
|
|
8
3
|
)
|
|
@@ -14,8 +9,8 @@ from .conversions import (
|
|
|
14
9
|
|
|
15
10
|
|
|
16
11
|
def keccak(
|
|
17
|
-
primitive:
|
|
18
|
-
hexstr:
|
|
19
|
-
text:
|
|
12
|
+
primitive: bytes | int | bool | None = None,
|
|
13
|
+
hexstr: HexStr | None = None,
|
|
14
|
+
text: str | None = None,
|
|
20
15
|
) -> bytes:
|
|
21
16
|
return bytes(keccak_256(to_bytes(primitive, hexstr, text)))
|
|
Binary file
|
faster_eth_utils/currency.py
CHANGED
|
@@ -46,22 +46,17 @@ class denoms:
|
|
|
46
46
|
|
|
47
47
|
MIN_WEI: Final = 0
|
|
48
48
|
MAX_WEI: Final = 2**256 - 1
|
|
49
|
+
DECIMAL_ZERO: Final = decimal.Decimal(0)
|
|
49
50
|
|
|
51
|
+
_NumberType = Union[int, float, str, decimal.Decimal]
|
|
50
52
|
|
|
51
|
-
def from_wei(number: int, unit: str) -> Union[int, decimal.Decimal]:
|
|
52
|
-
"""
|
|
53
|
-
Takes a number of wei and converts it to any other ether unit.
|
|
54
|
-
"""
|
|
55
|
-
if unit.lower() not in units:
|
|
56
|
-
raise ValueError(f"Unknown unit. Must be one of {'/'.join(units.keys())}")
|
|
57
53
|
|
|
54
|
+
def _from_wei(number: int, unit_value: decimal.Decimal) -> int | decimal.Decimal:
|
|
58
55
|
if number == 0:
|
|
59
56
|
return 0
|
|
60
57
|
|
|
61
58
|
if number < MIN_WEI or number > MAX_WEI:
|
|
62
|
-
raise ValueError("value must be between
|
|
63
|
-
|
|
64
|
-
unit_value = units[unit.lower()]
|
|
59
|
+
raise ValueError("value must be between 0 and 2**256 - 1")
|
|
65
60
|
|
|
66
61
|
with localcontext() as ctx:
|
|
67
62
|
ctx.prec = 999
|
|
@@ -71,13 +66,7 @@ def from_wei(number: int, unit: str) -> Union[int, decimal.Decimal]:
|
|
|
71
66
|
return result_value
|
|
72
67
|
|
|
73
68
|
|
|
74
|
-
def
|
|
75
|
-
"""
|
|
76
|
-
Takes a number of a unit and converts it to wei.
|
|
77
|
-
"""
|
|
78
|
-
if unit.lower() not in units:
|
|
79
|
-
raise ValueError(f"Unknown unit. Must be one of {'/'.join(units.keys())}")
|
|
80
|
-
|
|
69
|
+
def _to_wei(number: _NumberType, unit_value: decimal.Decimal) -> int:
|
|
81
70
|
if is_integer(number) or is_string(number):
|
|
82
71
|
d_number = decimal.Decimal(value=number) # type: ignore [arg-type]
|
|
83
72
|
elif isinstance(number, float):
|
|
@@ -87,12 +76,11 @@ def to_wei(number: Union[int, float, str, decimal.Decimal], unit: str) -> int:
|
|
|
87
76
|
else:
|
|
88
77
|
raise TypeError("Unsupported type. Must be one of integer, float, or string")
|
|
89
78
|
|
|
90
|
-
|
|
91
|
-
unit_value = units[unit.lower()]
|
|
92
|
-
|
|
93
|
-
if d_number == decimal.Decimal(0):
|
|
79
|
+
if d_number == DECIMAL_ZERO:
|
|
94
80
|
return 0
|
|
95
81
|
|
|
82
|
+
s_number = str(number)
|
|
83
|
+
|
|
96
84
|
if d_number < 1 and "." in s_number:
|
|
97
85
|
with localcontext() as ctx:
|
|
98
86
|
multiplier = len(s_number) - s_number.index(".") - 1
|
|
@@ -105,6 +93,52 @@ def to_wei(number: Union[int, float, str, decimal.Decimal], unit: str) -> int:
|
|
|
105
93
|
result_value = decimal.Decimal(value=d_number, context=ctx) * unit_value
|
|
106
94
|
|
|
107
95
|
if result_value < MIN_WEI or result_value > MAX_WEI:
|
|
108
|
-
raise ValueError("Resulting wei value must be between
|
|
96
|
+
raise ValueError("Resulting wei value must be between 0 and 2**256 - 1")
|
|
109
97
|
|
|
110
98
|
return int(result_value)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def from_wei(number: int, unit: str) -> int | decimal.Decimal:
|
|
102
|
+
"""
|
|
103
|
+
Takes a number of wei and converts it to any other ether unit.
|
|
104
|
+
"""
|
|
105
|
+
unit_key = unit.lower()
|
|
106
|
+
if unit_key not in units:
|
|
107
|
+
raise ValueError(f"Unknown unit. Must be one of {'/'.join(units.keys())}")
|
|
108
|
+
|
|
109
|
+
unit_value = units[unit_key]
|
|
110
|
+
|
|
111
|
+
return _from_wei(number, unit_value)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def to_wei(number: _NumberType, unit: str) -> int:
|
|
115
|
+
"""
|
|
116
|
+
Takes a number of a unit and converts it to wei.
|
|
117
|
+
"""
|
|
118
|
+
unit_key = unit.lower()
|
|
119
|
+
if unit_key not in units:
|
|
120
|
+
raise ValueError(f"Unknown unit. Must be one of {'/'.join(units.keys())}")
|
|
121
|
+
|
|
122
|
+
unit_value = units[unit_key]
|
|
123
|
+
|
|
124
|
+
return _to_wei(number, unit_value)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def from_wei_decimals(number: int, decimals: int) -> int | decimal.Decimal:
|
|
128
|
+
"""
|
|
129
|
+
Takes a number of wei and converts it to a decimal with the specified
|
|
130
|
+
number of decimals.
|
|
131
|
+
"""
|
|
132
|
+
unit_value = decimal.Decimal(10) ** decimal.Decimal(value=decimals)
|
|
133
|
+
|
|
134
|
+
return _from_wei(number, unit_value)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def to_wei_decimals(number: _NumberType, decimals: int) -> int:
|
|
138
|
+
"""
|
|
139
|
+
Takes a number of a unit and converts it to wei with the specified
|
|
140
|
+
number of decimals.
|
|
141
|
+
"""
|
|
142
|
+
unit_value = decimal.Decimal(10) ** decimal.Decimal(value=decimals)
|
|
143
|
+
|
|
144
|
+
return _to_wei(number, unit_value)
|