Common utility functions for python code that interacts with Ethereum
—
Comprehensive type validation utilities for common Python and Ethereum-specific data types. Provides reliable type checking for data validation pipelines.
Check for fundamental Python data types.
def is_integer(value) -> bool:
"""
Check if value is integer type (excluding boolean).
Args:
value: Value to check
Returns:
bool: True if value is int but not bool
"""
def is_boolean(value) -> bool:
"""
Check if value is boolean type.
Args:
value: Value to check
Returns:
bool: True if value is bool
"""
def is_string(value) -> bool:
"""
Check if value is string-like (str, bytes, or bytearray).
Args:
value: Value to check
Returns:
bool: True if value is any string type
"""
def is_text(value) -> bool:
"""
Check if value is text string (str only).
Args:
value: Value to check
Returns:
bool: True if value is str type
"""
def is_bytes(value) -> bool:
"""
Check if value is bytes-like object (bytes or bytearray).
Args:
value: Value to check
Returns:
bool: True if value is bytes or bytearray
"""Specialized numeric type validation.
def is_number(obj) -> bool:
"""
Check if object is numeric type (int, float, Decimal, but not bool).
Args:
obj: Object to check
Returns:
bool: True if object is numeric
"""
def is_null(obj) -> bool:
"""
Check if object is None.
Args:
obj: Object to check
Returns:
bool: True if object is None
"""Check for collection and sequence types.
def is_dict(obj) -> bool:
"""
Check if object is mapping type (dict or dict-like).
Args:
obj: Object to check
Returns:
bool: True if object implements mapping protocol
"""
def is_list(obj) -> bool:
"""
Check if object is list type.
Args:
obj: Object to check
Returns:
bool: True if object is list
"""
def is_tuple(obj) -> bool:
"""
Check if object is tuple type.
Args:
obj: Object to check
Returns:
bool: True if object is tuple
"""
def is_list_like(obj) -> bool:
"""
Check if object is sequence-like (list, tuple, etc. but not string).
Args:
obj: Object to check
Returns:
bool: True if object is sequence but not string type
"""from eth_utils import is_integer, is_string, is_bytes, is_boolean
def validate_transaction_input(value, input_type):
"""Validate transaction input based on expected type."""
if input_type == "uint256":
if not is_integer(value):
raise TypeError(f"Expected integer for uint256, got {type(value)}")
if value < 0 or value >= 2**256:
raise ValueError("uint256 value out of range")
elif input_type == "address":
if not is_string(value):
raise TypeError(f"Expected string for address, got {type(value)}")
# Additional address validation would go here
elif input_type == "bytes":
if not is_bytes(value) and not is_string(value):
raise TypeError(f"Expected bytes or hex string, got {type(value)}")
elif input_type == "bool":
if not is_boolean(value):
raise TypeError(f"Expected boolean, got {type(value)}")
return True
# Usage examples
validate_transaction_input(12345, "uint256") # Valid
validate_transaction_input("0x123...", "address") # Valid
validate_transaction_input(True, "bool") # Valid
# validate_transaction_input("123", "uint256") # Raises TypeErrorfrom eth_utils import is_list_like, is_dict, is_string, is_integer
def process_mixed_data(data):
"""Process data based on its type."""
if is_dict(data):
return {k: process_mixed_data(v) for k, v in data.items()}
elif is_list_like(data):
return [process_mixed_data(item) for item in data]
elif is_string(data):
return data.strip().lower()
elif is_integer(data):
return abs(data) # Ensure positive
else:
return str(data) # Convert to string as fallback
# Examples
result1 = process_mixed_data({"key": " VALUE "}) # {"key": "value"}
result2 = process_mixed_data([1, -2, " Text "]) # [1, 2, "text"]
result3 = process_mixed_data(-42) # 42from eth_utils import is_integer, is_string, is_bytes, is_list_like
def encode_function_call(function_name, parameters):
"""Encode function call with type validation."""
if not is_string(function_name):
raise TypeError("Function name must be string")
if not is_list_like(parameters):
raise TypeError("Parameters must be list-like")
encoded_params = []
for i, param in enumerate(parameters):
if is_integer(param):
# Encode integer parameter
encoded_params.append(f"uint256:{param}")
elif is_string(param):
# Encode string parameter
encoded_params.append(f"string:{param}")
elif is_bytes(param):
# Encode bytes parameter
encoded_params.append(f"bytes:{param.hex()}")
else:
raise TypeError(f"Unsupported parameter type at index {i}: {type(param)}")
return f"{function_name}({','.join(encoded_params)})"
# Usage
call = encode_function_call("transfer", ["0x123...", 1000])
print(call) # transfer(string:0x123...,uint256:1000)from eth_utils import is_dict, is_list_like, is_string
def validate_abi_element(abi_element):
"""Validate ABI element structure."""
if not is_dict(abi_element):
raise TypeError("ABI element must be dictionary")
required_fields = ["type", "name"]
for field in required_fields:
if field not in abi_element:
raise ValueError(f"Missing required field: {field}")
if not is_string(abi_element[field]):
raise TypeError(f"Field {field} must be string")
# Validate inputs if present
if "inputs" in abi_element:
inputs = abi_element["inputs"]
if not is_list_like(inputs):
raise TypeError("ABI inputs must be list")
for i, input_param in enumerate(inputs):
if not is_dict(input_param):
raise TypeError(f"Input parameter {i} must be dictionary")
if "type" not in input_param:
raise ValueError(f"Input parameter {i} missing type")
return True
# Example ABI validation
abi_element = {
"type": "function",
"name": "transfer",
"inputs": [
{"name": "to", "type": "address"},
{"name": "amount", "type": "uint256"}
]
}
validate_abi_element(abi_element) # Returns Truefrom eth_utils import is_integer, is_string, is_bytes, is_number
def safe_to_int(value):
"""Safely convert value to integer."""
if is_integer(value):
return value
elif is_string(value):
try:
return int(value, 0) # Auto-detect base (0x for hex)
except ValueError:
raise ValueError(f"Cannot convert string to int: {value}")
elif is_number(value):
return int(value)
else:
raise TypeError(f"Cannot convert {type(value)} to int")
def safe_to_string(value):
"""Safely convert value to string."""
if is_string(value):
return value if is_text(value) else value.decode('utf-8')
elif is_bytes(value):
return value.decode('utf-8')
else:
return str(value)
# Examples
print(safe_to_int("123")) # 123
print(safe_to_int("0x123")) # 291
print(safe_to_int(123.7)) # 123
print(safe_to_string(b"test")) # "test"from eth_utils import is_dict, is_string, is_integer, is_boolean
def validate_config(config):
"""Validate application configuration."""
if not is_dict(config):
raise TypeError("Configuration must be dictionary")
# Required string fields
string_fields = ["network_url", "contract_address"]
for field in string_fields:
if field not in config:
raise ValueError(f"Missing required field: {field}")
if not is_string(config[field]):
raise TypeError(f"Field {field} must be string")
# Required integer fields
if "block_confirmation_count" in config:
if not is_integer(config["block_confirmation_count"]):
raise TypeError("block_confirmation_count must be integer")
if config["block_confirmation_count"] < 1:
raise ValueError("block_confirmation_count must be positive")
# Optional boolean fields
if "debug_mode" in config:
if not is_boolean(config["debug_mode"]):
raise TypeError("debug_mode must be boolean")
return True
# Example configuration
config = {
"network_url": "https://mainnet.infura.io/v3/...",
"contract_address": "0x123...",
"block_confirmation_count": 12,
"debug_mode": False
}
validate_config(config) # Returns TrueThe module provides type tuples for isinstance checks:
bytes_types = (bytes, bytearray)
integer_types = (int,)
text_types = (str,)
string_types = (bytes, str, bytearray)from eth_utils import bytes_types, string_types, integer_types
# Use constants for isinstance checks
def is_bytes_like(value):
return isinstance(value, bytes_types)
def is_string_like(value):
return isinstance(value, string_types)
# Examples
print(is_bytes_like(b"test")) # True
print(is_bytes_like(bytearray())) # True
print(is_string_like("test")) # True
print(is_string_like(b"test")) # Truefrom eth_utils import (
is_string, is_integer, is_bytes, is_boolean,
is_list_like, is_dict, is_null
)
def validate_smart_contract_call(contract_address, function_name, parameters):
"""Validate smart contract call parameters."""
# Address validation
if is_null(contract_address) or not is_string(contract_address):
raise TypeError("Contract address must be non-null string")
# Function name validation
if is_null(function_name) or not is_string(function_name):
raise TypeError("Function name must be non-null string")
# Parameters validation
if is_null(parameters):
parameters = []
elif not is_list_like(parameters):
raise TypeError("Parameters must be list-like or None")
# Validate each parameter
for i, param in enumerate(parameters):
if is_null(param):
continue # Allow null parameters
elif not (is_string(param) or is_integer(param) or
is_bytes(param) or is_boolean(param)):
raise TypeError(f"Parameter {i} has unsupported type: {type(param)}")
return True