| num_convertA | Convert a big-integer between bases (hex/dec/bin/oct). Parses value as a from_base integer (a leading 0x/0b/0o and a - sign
are accepted) and renders it in to_base, prefixed for non-decimal output.
pad_bytes zero-fills the output to that byte width (a minimum, never
truncating); it is bit-aligned, so it is rejected for decimal output.
Arbitrary precision — a 32-byte RPC value converts losslessly.
Returns {value, from_base, to_base, result}.
Example: num_convert("255", "dec", "hex") -> result "0xff" |
| byte_orderA | Convert a value between host and network byte order (htons/htonl/ntohs/ntohl). data is decoded via input_format (hex default). from_order/to_order
are little|big|network|host: network is big-endian, host resolves to the
platform's sys.byteorder — so on a little-endian box from_order=host
to_order=network is htonl/htons. width (bytes) sets a fixed field size: a
shorter buffer is left zero-padded up to width, a longer one is split into
width-byte groups each swapped independently (array semantics); omit it to
swap the whole buffer as one field. Differing orders reverse each field; equal
orders only apply the width normalization. Returns {result, from_order,
to_order, width, output_format}; result is rendered via output_format.
Example: byte_order("0x12345678", "little", "big") -> result "78563412"
|
| time_convertA | Convert a timestamp between textual formats (ISO 8601/RFC 2822/HTTP/unix/strftime) and time zones. Parses value per from_format (auto sniffs iso8601/rfc2822/http/unix),
anchors a NAIVE result with from_zone (an input that already carries an
offset ignores it), shifts the instant into to_zone, and renders it as
to_format. Formats: iso8601 (RFC 3339), rfc2822, http (IMF-fixdate, always
GMT), unix/unix_ms/unix_us/unix_ns epoch, and strftime (needs format_pattern
on whichever side uses it). Zones are an IANA name (Europe/Budapest), UTC, or
a ±HH:MM offset. Returns {result, from_format, to_format, zone, unix};
from_format echoes the detected format under auto, unix is the integer
epoch-seconds anchor.
Example: time_convert("1700000000", "iso8601") -> result
"2023-11-14T22:13:20+00:00" |
| hashA | Compute a cryptographic, CRC, or fast non-crypto digest of bytes. length (output bytes) is required for shake_*; key keys blake2b/blake2s
(decoded with input_format); seed reseeds xxh*/fnv1a_*.
Returns {algorithm, digest, output_format, bits}; CRC and fast hashes
additionally report their integer value as int.
Example: hash("abc", "sha256") -> digest
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
|
| hash_fileA | Checksum a file on disk, optionally verifying it against an expected digest. Crypto digests stream the file in 1 MiB chunks; CRC/xxh/fnv read it whole.
When expected is supplied, verified reports whether it matches the digest
(compared as bytes, so case/0x/whitespace differences are tolerated).
Returns {algorithm, digest, path, size}, plus verified when expected is
given.
Example: hash_file("/etc/hostname", "sha256") -> {digest, path, size, ...} |
| hmacA | Compute or verify an HMAC authentication tag over data with a secret key. data and key are decoded with input_format / key_format. When
expected is supplied, valid reports a constant-time comparison against the
computed tag (tolerant of case/0x/whitespace in the expected value).
Returns {algorithm, mac, output_format}, plus valid when expected is given.
Example: hmac("msg", "key") -> mac "2d93cbc1be167bcb1637a4a23cbff01a..."
|
| encodeA | Encode bytes/text into a string form (base-N, URL, IDNA, bech32, hexdump, bytes32). data is decoded to bytes via input_format (text|hex|base64). options
is a per-scheme dict: padding (bool, default true — base32/base64 family),
alphabet (custom symbol set — base58/base62), hrp (required for
bech32/bech32m), width (bytes per line — hexdump, default 16). idna and
bytes32 read data as a text string / short string respectively. bytes32 is
a fixed-width 32-byte EVM word: inputs of <32 bytes are right-padded with
0x00; decode returns all 32 bytes (it does NOT strip trailing nulls, so the
round-trip is lossless — rstrip them yourself for a short string).
Returns {scheme, encoded}.
Example: encode("hello", "base64") -> encoded "aGVsbG8="
|
| decodeA | Decode a base-N/URL/IDNA/bech32/hexdump string back to bytes or text. The inverse of encode over the same scheme set. The recovered bytes are
rendered per output_format (text=UTF-8 | hex=bare, no 0x | base64); pick
hex/base64 for binary payloads that are not valid UTF-8. options carries
alphabet for base58/base62. base58/base58check/base45/idna need the
encoding extra.
Returns {scheme, decoded, output_format}; bech32/bech32m additionally return
their hrp.
Example: decode("aGVsbG8=", "base64") -> decoded "hello" |
| data_uriA | Build a data: URI from a payload, or parse one into its parts (RFC 2397). action=build (needs data, read via input_format): wraps it as
data:[media_type][;base64],<payload>; base64=true base64-encodes the
payload, else it is percent-encoded. action=parse (needs uri): returns
media_type (defaulting to text/plain when absent), the ;k=v parameters,
is_base64, and the decoded data rendered via output_format.
Example: data_uri("build", media_type="text/plain", data="hi") -> uri
"data:text/plain;base64,aGk=" |
| otpauth_uriA | Build an otpauth:// provisioning URI from parts, or parse one (Key URI Format). action=build (needs secret): assembles
otpauth://<type>/<label>?secret=...&issuer=... — secret is normalized to
canonical base32, type='hotp' requires counter, and counter/period
must match the type. action=parse (needs uri): returns type, the decoded
label (plus issuer/account split on the first ':'), secret, and the
algorithm/digits/period/counter parameters with their RFC defaults.
This codec never computes OTP codes; the base32 secret is passed through.
Example: otpauth_uri("build", label="alice@example.com", secret="JBSWY3DPEHPK3PXP",
issuer="Example") -> "otpauth://totp/Example:alice@example.com?secret=...&issuer=Example" |
| bytes_editA | Edit a hex byte-buffer: pad/trim to width, slice, concat, size, or 0x-prefix. data is hex (a leading 0x is optional). Actions:
pad: widen to length bytes with the fill byte on side (left=prepend,
right=append); never truncates if already wider. trim: strip the fill byte (default 00) from side (left=leading,
right=trailing) — the inverse of pad. slice: take data[start:end] (Python indexing; negatives allowed). concat: append each hex buffer in parts to data. size: report the byte length, buffer unchanged. prefix: side=left adds a 0x prefix, side=right strips it.
Returns {action, result, size}: result is the 0x-prefixed hex buffer (bare
hex when prefix-stripping), size its byte length.
Example: a 20-byte address -> 32-byte log topic:
bytes_edit("pad", "0x1234", length=4, side="left") -> result "0x00001234" |
| unicode_normalizeA | Normalize text to a Unicode normalization form (NFC/NFD/NFKC/NFKD). NFC/NFD are canonical compose/decompose; NFKC/NFKD also fold compatibility
characters (ligatures, full-width, circled digits) to their plain forms.
changed is true when result differs from the input — i.e. the text was
not already in form. Returns {form, result, changed}.
Example: unicode_normalize("fi", "NFKC") -> result "fi" (fi ligature, ① -> 1) |
| charset_transcodeA | Convert text between character encodings (e.g. latin-1/cp1252 <-> utf-8). The input is encoded under from_charset to recover its raw bytes, which are
then decoded under to_charset. If the bytes aren't valid to_charset text
they're returned as bare hex with output_format='hex' (otherwise 'text').
errors selects the codec error handler (strict|replace|ignore|…).
Returns {from_charset, to_charset, result, output_format}.
Example: charset_transcode("café", "cp1252", "utf-8") -> result "café" |
| string_escapeA | Escape text for a source-code or markup context (JSON/JS/C/shell/HTML/...). style picks the convention: json|js|python|c|backslash (backslash escapes),
html|xml (entities), unicode_escape (\uXXXX/\xNN), quoted_printable, or
mime_word (=?UTF-8?B?...?=). shell yields a paste-safe single-quoted token.
For URL %-escaping use encode(scheme='url') instead. An unknown style raises
ValueError. Returns {style, result}. Inverse: string_unescape.
Example: string_escape('a"b', "json") -> result 'a"b'
|
| string_unescapeA | Reverse a source-code or markup escaping back to the original text. Style-for-style inverse of string_escape (json|js|python|c|backslash escape
sequences, html|xml entities, unicode_escape, quoted_printable, mime_word,
and shell). Malformed escape sequences (and an unknown style) raise
ValueError. Returns {style, result}.
Example: string_unescape('a\nb', "json") -> result "ab" |
| codepointsA | Break text into its code points with names and UTF-8/16/32 byte views. Returns one entry per Unicode scalar (astral characters stay whole): the
char, its codepoint as 'U+XXXX', the Unicode name (or a
placeholder for unnamed control/format/private-use scalars), and big-endian
utf8/utf16/utf32 byte views as hex. count is the code-point length,
which differs from len() only for surrogate-pair-bearing input.
Example: codepoints("é") -> count 1, char "é" at codepoint "U+00E9" |
| password_hashA | Hash a password into a verifiable storage string, or check one against it. action=hash (needs scheme) returns encoded, a self-describing string that
carries the scheme, its cost params and the salt: bcrypt's $2b$… and
argon2's PHC string verbatim, and for the stdlib schemes the PHC-shaped
$scrypt$ln=14,r=8,p=1$<salt>$<hash> / $pbkdf2-sha256$i=600000$<salt>$<hash>
(base64 fields, padding stripped). action=verify reads the scheme back out of
encoded and returns {"valid": true|false} — a wrong password is a result,
not an error (§2.0.5); only a malformed encoded raises. The password itself
is never echoed (§2.0.6). bcrypt/argon2* need the crypto extra.
Example: password_hash("hash", "hunter2", scheme="pbkdf2",
params={"iterations": 100000}) -> {"encoded": "$pbkdf2-sha256$i=100000$..."} |
| derive_keyA | Derive raw key bytes from a password or secret via a KDF (PBKDF2/scrypt/HKDF). Returns the key rendered per output_format, plus the kdf, length,
salt and params actually used — everything needed to repeat the
derivation. Fully deterministic: the same inputs always give the same key, so
an omitted salt means an empty one rather than a fresh random one. Use
pbkdf2/scrypt to stretch a human password, and hkdf only to expand a secret
that is already high-entropy (a shared secret, another key). To STORE a
password for later checking, use password_hash instead — its output is a
self-describing string built to be compared against.
Example: derive_key("hunter2", kdf="pbkdf2", salt="0011223344556677",
length=32) -> {"key": "a3f1...", "params": {"iterations": 600000, ...}} |
| randomA | Generate cryptographically secure random bytes, a token, or a passphrase. All randomness is drawn from the OS CSPRNG (secrets). kind selects the
shape and which sizing arg applies: bytes|hex|urlsafe draw nbytes (default
32) random bytes — bytes renders them via output_format (hex/base64), hex
is the same bytes as hex, urlsafe is RFC 4648 url-safe base64; token is a
length-character (default 32) alphanumeric [A-Za-z0-9] string; passphrase
joins words (default 6) words with separator (default '-'), drawn from
wordlist or the bundled EFF large diceware list. Returns {kind, value,
entropy_bits}; the value is the only secret and is never logged elsewhere.
Example: random("hex", nbytes=4) -> value "6a08ed95" (8 hex chars, 32 bits) |
| id_generateA | Generate one or more identifiers (UUID / ULID / nanoid). All randomness is drawn from the OS CSPRNG (secrets). kind selects the
family and which args apply. uuid honours version (default 4): v1 is
time-based with a random node ID rather than the host MAC, v4 is 122 random
bits, v5 is the SHA-1 of name within namespace (dns|url|oid|x500 or a
UUID string) and so is deterministic — a count above 1 repeats it — and v7
is a 48-bit millisecond timestamp plus 74 random bits, which sorts by
creation time. ulid is the same clock rendered as 26 Crockford base32
characters, also time-sortable. nanoid draws size (default 21) symbols from
alphabet (default 64 url-safe chars). Returns {kind, ids} plus the resolved
version (uuid) or size (nanoid).
Example: id_generate("uuid", version=5, namespace="dns", name="example.com")
-> ids ["cfbff0d1-9375-5685-968c-48ce8b15ae17"] |
| eth_hashA | Compute an Ethereum hash: keccak-256, EIP-191, EIP-712, or EIP-7702. Returns {kind, hash}. For kind=eip712 the result also carries
{domain_separator, struct_hash}, the two EIP-712 component hashes. For
kind=eip7702 data is the authorization tuple {chainId, address, nonce} and
the result carries the preimage that was hashed, 0x05 || rlp([chain_id,
address, nonce]) — the 0x05 keeps a signed authorization from ever being
replayed as a transaction. A chainId of 0 is not a missing value there: it
authorizes the delegation on every chain. Note keccak-256 is the pre-NIST
Ethereum variant, not hashlib's SHA3-256. Example: eth_hash("keccak256", "hello", "text") ->
hash="0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8". |
| eth_selectorA | Derive the 4-byte function selector or 32-byte event topic from a signature. Returns {kind, signature (canonicalized), selector} for functions, or
{kind, signature, topic0} for events. Example: eth_selector("transfer(address,uint256)") -> selector="0xa9059cbb". |
| rlp_codecA | RLP-encode structured data, or RLP-decode a hex string. Encode data is a recursive structure: a leaf (hex string, or a non-negative
integer stored minimal big-endian) or a JSON array of items (nested allowed);
a JSON-array string is parsed too. action=encode -> {encoded:'0x...'}.
Decode data is a 0x-hex string; action=decode -> {decoded} with leaves as
0x-hex and lists as arrays. Example: rlp_codec("encode", ["0x636174"]) -> encoded="0xc483636174". |
| abi_codecA | ABI-encode values or ABI-decode call/return/log data. types is a list of ABI type strings (e.g. ["uint256", "address",
"(uint8,bytes)[]"]); aliases like uint/int/byte are normalized.
action=encode (needs values) -> {encoded, mode}. mode=packed is
abi.encodePacked (tight, no padding) and is encode-only. action=decode
(needs data, standard only) -> {values}; ints are returned as decimal
strings and addresses EIP-55 checksummed.
Example: abi_codec("encode", ["uint256"], [69]) -> encoded="0x00..0045"
(the 32-byte word 0x...0045). |
| abi_inspectA | List an ABI's entries with their canonical signatures and selectors. Accepts a JSON ABI or human-readable declarations and returns BOTH forms for
every entry, so it converts in either direction. Returns {count, entries,
selectors, topics}: entries carries {type, name, signature (canonical),
human, inputs, outputs} per entry plus selector for functions and errors,
topic0 and anonymous for events, and stateMutability when known;
inputs/outputs are JSON ABI shape, so feeding human-readable text in and
reading them out is the human -> JSON ABI direction, and human is the
reverse. selectors maps every 4-byte selector to its canonical signature
and topics every topic0 — the lookup table eth_calldata, eth_log_decode and
eth_revert_decode take as input. collisions is added only if two distinct
signatures share a selector. constructor/fallback/receive entries carry no
signature or selector, having none. Example: abi_inspect("function transfer(address to, uint256 amount)") ->
selectors={"0xa9059cbb": "transfer(address,uint256)"}. |
| eth_calldataA | Split calldata into named, typed arguments — or build calldata from them. signature is human-readable, e.g. "transfer(address to, uint256 amount)";
parameter names are optional and come back as args[].name (null when the
signature declares none), with args[].components naming a struct's members.
action=encode (needs values) -> {action, signature (canonical), selector,
calldata, args}; values may be omitted for a zero-argument signature.
action=decode (needs data) -> {action, signature, selector,
selector_matches, args}; ints are decimal strings and addresses EIP-55
checksummed. When the calldata's leading 4 bytes are not this signature's
selector the arguments are still decoded, but selector_matches is false and
data_selector + reason report the mismatch — the values are then almost
certainly meaningless.
Example: eth_calldata("decode", "transfer(address to, uint256 amount)",
"0xa9059cbb...") -> args=[{name="to", ...}, {name="amount", ...}]. |
| eth_log_decodeA | Turn a receipt log's topics and data into named event arguments. signature is human-readable, e.g. "Transfer(address indexed from, address
indexed to, uint256 value)"; indexed is what splits the arguments between
topics and data. Returns {signature (canonical), anonymous, topic0,
topic0_matches, args}; topic0 and topic0_matches are omitted for an
anonymous event, which carries no topic0 to check. args lists EVERY
argument in declaration order — indexed and not, interleaved — as
{name (null when undeclared), type, value, indexed}, plus components on
tuple args. Only a value type (uintN/intN/bool/address/bytesN) survives in a
topic: every array, every struct, and bytes/string are keccak-hashed into it,
so those come back with value null plus {hashed: true, hash} — enough to
match against keccak of a candidate, never the value itself. A topics[0] that
is not this signature's topic0 is soft (topic0_matches false, plus
log_topic0 and reason), but a topic COUNT that contradicts the signature
raises: ERC-20 and ERC-721 Transfer share a topic0 and differ only there.
Example: eth_log_decode("Transfer(address indexed from, address indexed to,
uint256 value)", [topic0, from_word, to_word], "0x..0de0b6b3a7640000") ->
args=[{name="from", ...}, {name="to", ...}, {name="value", ...}]. |
| eth_revert_decodeA | Decode a failed call's revert data into a human-readable reason. Returns {kind, ...} where kind selects the rest of the payload:
'empty' (no revert data at all) -> {reason}; 'error' (Error(string), the
require/revert message) -> {selector, signature, reason}; 'panic'
(Panic(uint256), a compiler check) -> {selector, signature, code, meaning};
'custom' (a user-declared error, needs signature) -> {selector, signature,
selector_matches, args} with args as {name, type, value} exactly as
eth_calldata reports them; 'unknown' (an unrecognized selector and no
signature given) -> {selector, reason}. A signature whose selector is not
the one in data still decodes, but selector_matches is false and reason
says so. Example: eth_revert_decode("0x08c379a0...") -> kind="error",
reason="ERC20: transfer amount exceeds balance". |
| eth_bytecodeA | Disassemble EVM bytecode, scrape its selectors, or read its solc metadata. code is hex runtime bytecode. The trailing solc CBOR metadata is data, not
code, so it is excluded from both the disassembly and the selector scrape and
reported as metadata_offset instead.
action=disassemble -> {size, code_size, count, offset, instructions} with each
instruction {pc, opcode, name} plus push_data for PUSH1..PUSH32; an
unassigned byte has name null and unknown, and code ending mid-immediate
is flagged truncated. Output is capped at limit instructions, which adds
{truncated, next_offset} — page with offset, or pass limit=0 for all.
action=selectors -> {count, selectors, sites}: every PUSH4 the dispatcher then
compares (EQ, or GT/LT in solc's binary-search dispatcher), decoded rather
than grepped, so a PUSH4 pattern inside another push's immediate cannot
masquerade as one. sites gives the {selector, pc, op} of each comparison.
This is a heuristic on unstructured code: an ERC-165 interface id is a
PUSH4 compared with EQ and is indistinguishable from a selector here, and
an unconventional dispatcher may hide one. Feed the results to
abi_inspect's selectors map (or a 4-byte database) to name them.
action=metadata -> {present, offset, length, cbor, metadata} plus
solc_version and, when the hash is an IPFS CIDv0 multihash, ipfs_cid.
Code compiled with metadata stripped returns present=false, not an error.
Example: eth_bytecode("selectors", "0x6080...") ->
selectors=["0xa9059cbb", "0x70a08231"]. |
| eth_userop_hashA | Compute the ERC-4337 userOpHash: an operation's id and signing digest. The hash binds the operation to entry_point and chain_id, so the same
operation cannot be replayed against another EntryPoint or another chain.
version decides the rule and defaults to reading it off the canonical
EntryPoint address (0.6 0x5FF1…2789, 0.7 0x0000000071727De2…da032, 0.8
0x4337084d…f108, the same on every chain); pass it explicitly for a custom
deployment. v0.6 encodes six separate gas fields; v0.7 packs
verificationGasLimit/callGasLimit and maxPriorityFeePerGas/maxFeePerGas into
one word each (16 bytes apiece, high half first); v0.8 hashes that same
packed struct as EIP-712 typed data. The unpacked eth_sendUserOperation JSON
is accepted for v0.7/v0.8 and packed here, which is the fiddly half.
Returns {version, entry_point, chain_id, user_op_hash} plus the intermediate
values — op_hash for 0.6/0.7, domain_separator and struct_hash for
0.8 — and packed (the words that were hashed) for 0.7/0.8. signature is
never read: it signs this hash, so it cannot be part of it. Example: eth_userop_hash(user_op, "0x0000000071727De22E5E9d8BAf0edAc6f37da032", -> version="0.7", user_op_hash="0x…".
|
| eth_storage_slotA | Compute a storage slot: a mapping/array entry, or a well-known layout's root. layout: {"kind": …} — the first two describe a layout you declared, the rest
are the standard constant slots, which need no "slot" of their own:
mapping -> needs "slot" and key; "key_type" (default uint256). For
nested mappings pass key (and "key_type") as lists.
dynamic_array -> needs "slot" and index; optional "element_size" (slots).
eip1967 -> the proxy slots, keccak256(label) - 1. Optional "name":
implementation (default), admin, beacon, or rollback.
eip1822 -> UUPS proxiableUUID, keccak256("PROXIABLE") — no -1.
erc7201 -> namespaced storage root for "namespace",
keccak256(abi.encode(keccak256(ns) - 1)) & ~0xff. An
erc7201: annotation prefix on the namespace is stripped.
diamond -> EIP-2535 diamond storage, plain keccak256("namespace").
Returns {slot, slot_hex}: the slot as a decimal string and a 0x 32-byte word,
plus formula (and name/namespace) for the constant layouts. Every
constant is derived by keccak here, not pasted from the EIP. The results
compose: feed a namespaced root back in as another layout's "slot" to reach
a mapping or array declared inside that struct, and use index to step to a
later member of it. Example: eth_storage_slot({"kind":"eip1967"}) ->
slot_hex="0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc". |
| eth_eoa_addressA | Derive an EOA's Ethereum address and public key from its private key. The public key is the curve point k*G, serialized uncompressed (0x04 || X || Y);
the address is the last 20 bytes of keccak256(X || Y), EIP-55 checksummed. This
is the externally-owned-account counterpart to eth_contract_address — it
derives, it does not create an account. Returns {address, public_key}; the
private key is never echoed back. Exactly one of private_key (inline hex) or private_key_file (a path the
server reads, which keeps the key out of the conversation) is required. Example: eth_eoa_address(
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80") ->
address="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266". |
| eth_contract_addressA | Compute a contract's CREATE or CREATE2 deployment address. scheme=create -> needs nonce; address = keccak256(rlp([deployer, nonce]))[12:]
scheme=create2 -> needs salt and init_code;
address = keccak256(0xff ++ deployer ++ salt ++
keccak256(init_code))[12:]
Returns {address}, EIP-55 checksummed. Computes only — nothing is deployed. Example: eth_contract_address("create",
"0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0", nonce=0) ->
address="0xcd234A471b72ba2F1Ccf0A70FCABA648a5eeCD8d". |
| bip39A | Generate, validate, or convert a BIP-39 mnemonic to a seed. action=generate -> {action, mnemonic, word_count, strength}. With entropy the
mnemonic is deterministic; without it, fresh CSPRNG entropy of strength bits.
action=validate -> {action, valid, word_count} plus a reason when invalid — a
bad mnemonic is a soft result, not an error (§2.0.5).
action=to_seed -> {action, seed, word_count}: the 64-byte seed as 0x-hex, ready
for bip32_derive. PBKDF2-HMAC-SHA512(mnemonic, "mnemonic"+passphrase, 2048).
An invalid mnemonic raises here; use action=validate to inspect it first. Neither the mnemonic, the entropy, nor the passphrase is ever echoed back. Example: bip39("to_seed", mnemonic="abandon abandon abandon abandon abandon
abandon abandon abandon abandon abandon abandon about") -> seed="0x5eb00bbd..." |
| eth_tx_codecA | Serialize tx fields into a raw transaction, or decode a raw tx. action=encode (needs fields) serializes the supplied fields (it does not
sign) -> {type, raw:'0x...', hash, signing_hash}. fields is an object; the
type is taken from a type key or inferred from which fields are present
(maxFeePerGas -> 1559, blobVersionedHashes -> 4844, accessList -> 2930, else
legacy). Numbers accept int / decimal / 0x-hex; to/data are 0x-hex.
action=decode (needs data, a 0x-hex raw tx) -> {type, fields, hash,
signing_hash, from}, recovering from from the signature; numeric fields
come back as decimal strings, addresses EIP-55 checksummed. signing_hash is the digest the sender signs: keccak256 of the payload
without the signature (typed: type_byte || rlp(fields minus yParity/r/s);
legacy EIP-155: rlp(fields[:6] + [chainId, 0, 0]); pre-EIP-155:
rlp(fields[:6])). hash is the tx hash, which covers the signature too, so
it is only meaningful once signed. To sign: encode the unsigned fields, sign
signing_hash with eth_sign, then encode again with r, s and yParity —
legacy instead takes v = chainId*2 + 35 + yParity (27 + yParity
pre-EIP-155).
Example: eth_tx_codec("encode", fields={"nonce":0,"gasPrice":"0x09184e72a000",
"gasLimit":"0x2710","to":"0x00..00","value":0,"data":"0x"}) -> type=0,
raw="0xe5808609184e72a00082271094...808080". |
| eth_address_caseA | Apply or verify an EIP-55 mixed-case address checksum. action=encode -> {action, address} with the checksummed (mixed-case) address.
action=verify -> {action, address (checksummed), valid}, plus a reason when
the supplied casing does not match the EIP-55 checksum. Example: eth_address_case("encode",
"0x52908400098527886e0f7030069857d2e4169ee7") ->
address="0x52908400098527886E0F7030069857D2E4169EE7". |
| ens_namehashA | Compute the EIP-137 namehash (and labelhash) of an ENS name. The name is hashed exactly as given; EIP-137 expects it already UTS-46
normalized (use unicode_normalize first if needed), and empty labels from a
stray dot are rejected. Returns {name, namehash, labelhash}, where labelhash
is the keccak of the leftmost label — for a single label that is the .eth
registrar token id for that name. Example: ens_namehash("vitalik.eth") ->
namehash="0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835". |
| bip32_deriveA | Derive an HD child key and its Ethereum address from a seed along a BIP-32/44 path. The master key comes from HMAC-SHA512("Bitcoin seed", seed); each path step
derives a child via BIP-32 CKDpriv (hardened steps use the parent private key,
normal steps its compressed public key). The Ethereum address is the last 20
bytes of keccak256(uncompressed pubkey), EIP-55 checksummed. Returns {path,
depth, private_key, public_key, chain_code, address}; the derived child
private_key IS returned (it is new output, not the seed), but the input seed is
never echoed. Example: bip32_derive(<64-byte seed hex>, "m/44'/60'/0'/0/0") ->
{"address": "0x...", "private_key": "0x...", ...}. |
| eth_signA | Sign, verify, ecrecover, or reformat a secp256k1 signature over a 32-byte hash. This signs a raw digest — unlike the JSON-RPC eth_sign/personal_sign, it
adds no "\x19Ethereum Signed Message" prefix. Hash a message first with
eth_hash (kind=eip191 for personal_sign, eip712 for typed data), or pass a
transaction's signing hash (eth_tx_codec's signing_hash) or a user
operation's hash (eth_userop_hash). action=sign (message_hash, private_key_file) -> {signature (65-byte, v=27/28),
r, s, v, yParity, eip2098, address}. The nonce is RFC 6979, so the result is
deterministic and matches eth_account/ethers; s is always low (EIP-2).
address is the signer's, to confirm the right key was used. The key is
never echoed.
action=verify (message_hash, signature, address) -> {valid, recovered, low_s};
a signature that recovers no key is soft: valid false plus reason.
action=recover (message_hash, signature) -> {address, low_s}.
action=convert (signature, signature_format) -> {format, result, low_s}.
low_s is false for a malleable high-s signature: the ecrecover precompile
accepts it, but Ethereum transactions and OpenZeppelin's ECDSA reject it. Example: eth_sign("sign", message_hash="0x…32 bytes…",
private_key_file="~/keys/dev.key") -> {signature: "0x…1b", r, s, v: 27, …}. |
| infoA | Discovery / health-check entrypoint: report availability and enabled toolsets. Returns six keys: status ("available"), name, version (package version),
python (runtime version), mcp_sdk (MCP SDK version, or "unknown"), and
toolsets (sorted list of live optional toolsets).
Example: {"status":"available","name":"mcp-bytesmith","version":"0.1.0",
"python":"3.12.3","mcp_sdk":"1.2.0","toolsets":["ethereum","serialize"]} |