add
This commit is contained in:
171
ccxt/static_dependencies/ethereum/utils/address.py
Normal file
171
ccxt/static_dependencies/ethereum/utils/address.py
Normal file
@@ -0,0 +1,171 @@
|
||||
import re
|
||||
from typing import (
|
||||
Any,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
||||
from ..typing import (
|
||||
Address,
|
||||
AnyAddress,
|
||||
ChecksumAddress,
|
||||
HexAddress,
|
||||
HexStr,
|
||||
)
|
||||
|
||||
from .conversions import (
|
||||
hexstr_if_str,
|
||||
to_hex,
|
||||
to_bytes,
|
||||
)
|
||||
from ...keccak import (
|
||||
SHA3 as keccak,
|
||||
)
|
||||
from .hexadecimal import (
|
||||
add_0x_prefix,
|
||||
decode_hex,
|
||||
encode_hex,
|
||||
remove_0x_prefix,
|
||||
)
|
||||
from .types import (
|
||||
is_bytes,
|
||||
is_text,
|
||||
)
|
||||
|
||||
_HEX_ADDRESS_REGEXP = re.compile("(0x)?[0-9a-f]{40}", re.IGNORECASE | re.ASCII)
|
||||
|
||||
|
||||
def is_hex_address(value: Any) -> bool:
|
||||
"""
|
||||
Checks if the given string of text type is an address in hexadecimal encoded form.
|
||||
"""
|
||||
if not is_text(value):
|
||||
return False
|
||||
return _HEX_ADDRESS_REGEXP.fullmatch(value) is not None
|
||||
|
||||
|
||||
def is_binary_address(value: Any) -> bool:
|
||||
"""
|
||||
Checks if the given string is an address in raw bytes form.
|
||||
"""
|
||||
if not is_bytes(value):
|
||||
return False
|
||||
elif len(value) != 20:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def is_address(value: Any) -> bool:
|
||||
"""
|
||||
Is the given string an address in any of the known formats?
|
||||
"""
|
||||
if is_hex_address(value):
|
||||
if _is_checksum_formatted(value):
|
||||
return is_checksum_address(value)
|
||||
return True
|
||||
|
||||
if is_binary_address(value):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def to_normalized_address(value: Union[AnyAddress, str, bytes]) -> HexAddress:
|
||||
"""
|
||||
Converts an address to its normalized hexadecimal representation.
|
||||
"""
|
||||
try:
|
||||
hex_address = hexstr_if_str(to_hex, value).lower()
|
||||
except AttributeError:
|
||||
raise TypeError(f"Value must be any string, instead got type {type(value)}")
|
||||
if is_address(hex_address):
|
||||
return HexAddress(HexStr(hex_address))
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Unknown format {repr(value)}, attempted to normalize to "
|
||||
f"{repr(hex_address)}"
|
||||
)
|
||||
|
||||
|
||||
def is_normalized_address(value: Any) -> bool:
|
||||
"""
|
||||
Returns whether the provided value is an address in its normalized form.
|
||||
"""
|
||||
if not is_address(value):
|
||||
return False
|
||||
else:
|
||||
is_equal = value == to_normalized_address(value)
|
||||
return cast(bool, is_equal)
|
||||
|
||||
|
||||
def to_canonical_address(address: Union[AnyAddress, str, bytes]) -> Address:
|
||||
"""
|
||||
Convert a valid address to its canonical form (20-length bytes).
|
||||
"""
|
||||
return Address(decode_hex(to_normalized_address(address)))
|
||||
|
||||
|
||||
def is_canonical_address(address: Any) -> bool:
|
||||
"""
|
||||
Returns `True` if the `value` is an address in its canonical form.
|
||||
"""
|
||||
if not is_bytes(address) or len(address) != 20:
|
||||
return False
|
||||
is_equal = address == to_canonical_address(address)
|
||||
return cast(bool, is_equal)
|
||||
|
||||
|
||||
def is_same_address(left: AnyAddress, right: AnyAddress) -> bool:
|
||||
"""
|
||||
Checks if both addresses are same or not.
|
||||
"""
|
||||
if not is_address(left) or not is_address(right):
|
||||
raise ValueError("Both values must be valid addresses")
|
||||
else:
|
||||
return bool(to_normalized_address(left) == to_normalized_address(right))
|
||||
|
||||
|
||||
def to_checksum_address(value: Union[AnyAddress, str, bytes]) -> ChecksumAddress:
|
||||
"""
|
||||
Makes a checksum address given a supported format.
|
||||
"""
|
||||
norm_address = to_normalized_address(value)
|
||||
address_hash = encode_hex(keccak(to_bytes(text=remove_0x_prefix(HexStr(norm_address)))))
|
||||
|
||||
checksum_address = add_0x_prefix(
|
||||
HexStr(
|
||||
"".join(
|
||||
(
|
||||
norm_address[i].upper()
|
||||
if int(address_hash[i], 16) > 7
|
||||
else norm_address[i]
|
||||
)
|
||||
for i in range(2, 42)
|
||||
)
|
||||
)
|
||||
)
|
||||
return ChecksumAddress(HexAddress(checksum_address))
|
||||
|
||||
|
||||
def is_checksum_address(value: Any) -> bool:
|
||||
if not is_text(value):
|
||||
return False
|
||||
|
||||
if not is_hex_address(value):
|
||||
return False
|
||||
is_equal = value == to_checksum_address(value)
|
||||
return cast(bool, is_equal)
|
||||
|
||||
|
||||
def _is_checksum_formatted(value: Any) -> bool:
|
||||
unprefixed_value = remove_0x_prefix(value)
|
||||
return (
|
||||
not unprefixed_value.islower()
|
||||
and not unprefixed_value.isupper()
|
||||
and not unprefixed_value.isnumeric()
|
||||
)
|
||||
|
||||
|
||||
def is_checksum_formatted_address(value: Any) -> bool:
|
||||
return is_hex_address(value) and _is_checksum_formatted(value)
|
||||
Reference in New Issue
Block a user