Low-level Ethereum cryptographic primitives used to sign Polymarket orders.
Wraps the two native dependencies — ExKeccak for keccak-256 and ExSecp256k1
for ECDSA secp256k1 — behind a small, total API so the rest of the codebase
never touches the NIFs directly:
keccak256/1— the keccak-256 hash (Ethereum's hash, not FIPS SHA3-256).address_from_private_key/1— the 20-byte Ethereum address for a key.sign_digest/2— an Ethereum-style 65-byter ‖ s ‖ vsignature over a pre-computed 32-byte digest.
All functions raise ArgumentError on malformed input (wrong byte sizes); a
failure here is a programming error, not a recoverable runtime condition.
Summary
Types
A 20-byte Ethereum address.
A 32-byte digest, e.g. a keccak-256 hash.
A 32-byte secp256k1 private key.
A 65-byte r ‖ s ‖ v signature, with v in 27..28.
Functions
Derives the 20-byte Ethereum address controlled by private_key.
Computes the keccak-256 hash of data (a binary or iodata).
Signs a pre-computed 32-byte digest with private_key, returning a 65-byte
Ethereum signature r (32) ‖ s (32) ‖ v (1), where v is the recovery id
normalised to 27 or 28.
Renders a 20-byte address as its EIP-55 mixed-case checksummed 0x string.
Renders a binary as a lowercase 0x-prefixed hex string.
Types
@type address() :: <<_::160>>
A 20-byte Ethereum address.
@type digest() :: <<_::256>>
A 32-byte digest, e.g. a keccak-256 hash.
@type private_key() :: <<_::256>>
A 32-byte secp256k1 private key.
@type signature() :: <<_::520>>
A 65-byte r ‖ s ‖ v signature, with v in 27..28.
Functions
@spec address_from_private_key(private_key()) :: address()
Derives the 20-byte Ethereum address controlled by private_key.
The address is the last 20 bytes of the keccak-256 hash of the 64-byte
uncompressed public key (the key without its leading 0x04 prefix).
Computes the keccak-256 hash of data (a binary or iodata).
This is the hash function Ethereum uses everywhere — address derivation,
EIP-712, function selectors. It differs from the FIPS-202 :sha3_256 exposed
by :crypto, which uses different padding and produces different output.
@spec sign_digest(digest(), private_key()) :: signature()
Signs a pre-computed 32-byte digest with private_key, returning a 65-byte
Ethereum signature r (32) ‖ s (32) ‖ v (1), where v is the recovery id
normalised to 27 or 28.
The signature is deterministic (RFC 6979): the same digest and key always yield the same bytes.
Renders a 20-byte address as its EIP-55 mixed-case checksummed 0x string.
Each hex letter is upper-cased when the corresponding nibble of the keccak-256
hash of the lowercase address string is >= 8. Polymarket's L2 POLY_ADDRESS
header expects this form (the order wire body, by contrast, uses lowercase).
Renders a binary as a lowercase 0x-prefixed hex string.