@ethernauta/abi
v0.0.48
Published
ABI encode/decode codecs for Ethernauta — function signatures, event topics, parameter encoding/decoding.
Maintainers
Readme
Philosophy
This module is an un-opinionated representation of the Solidity ABI specification. It covers two responsibilities:
- Runtime ABI codec — encode function calls / constructor calls, decode function results, decode
Error(string)/Panic(uint256)revert payloads, encode + decode event topics and logs. - Code generation — emit ready-to-use TypeScript methods from an ABI JSON or a Foundry artifact.
Generated methods come in two flavors:
Callable<T>for view / pure functions — consumed by a contract resolver, fireseth_call.Signable<Bytes>for state-changing functions — consumed by a signer resolver, returns the signed raw transaction ready foreth_sendRawTransaction.
Modules
- abi [NPM]
- chain [NPM]
- cli [NPM]
- core [NPM]
- crypto [NPM]
- eip [NPM]
- ens [NPM]
- erc [NPM]
- eth [NPM]
- react [NPM]
- transaction [NPM]
- transport [NPM]
- utils [NPM]
- wallet
API
Encode a function call
import { build_signature, encode_function_call, function_selector, to_selector } from "@ethernauta/abi"
import { bytes_to_hex } from "@ethernauta/utils"
const signature = build_signature("transfer", ["address", "uint256"])
const selector = function_selector(signature) // Bytes4 — keccak256(signature)[0:4]
const calldata = encode_function_call(
signature,
["address", "uint256"],
["0x515e9e0565fdddd4f8a9759744734154da453585", 1n],
)
const input = bytes_to_hex(calldata) // "0xa9059cbb000000…"
// Also exported: `to_selector(name, inputs)` — same as
// `function_selector(build_signature(name, inputs))`.Encode a constructor call
import { encode_constructor_call } from "@ethernauta/abi"
const init_code = encode_constructor_call(
bytecode, // Uint8Array — runtime + constructor
["address", "uint256"], // constructor input types
["0x…", 1n],
)Decode a function result
import { decode_function_result } from "@ethernauta/abi"
const [decoded] = decode_function_result(
["uint256"],
"0x0000000000000000000000000000000000000000000000000000000000000002",
)
// 2nDecode raw call data
Inverse of encode_function_call — useful for wallets inspecting an unknown input field.
import { decode_function_call } from "@ethernauta/abi"
const args = decode_function_call(["address", "uint256"], calldata)Decode a revert payload
import { decode_revert_reason } from "@ethernauta/abi"
const reason = decode_revert_reason(revert_bytes)
// { kind: "error", message: "ERC20: transfer to the zero address" }
// or { kind: "panic", code: 0x11 }
// or { kind: "raw", data: "0x…" }RevertReasonSchema is exported for callers that want to validate / parse external payloads.
Encode and decode event topics + logs
import {
encode_event_topics,
event_topic_hash,
decode_event_log,
decode_logs,
} from "@ethernauta/abi"
// Build the topic filter for an event signature
const topics = encode_event_topics({
signature: "Transfer(address,address,uint256)",
indexed: ["address", "address", "uint256"],
filter: [from_address, undefined, undefined],
})
// Hash a single event signature
const topic0 = event_topic_hash("Transfer(address,address,uint256)")
// Decode a single log against a known ABI shape
const event = decode_event_log({
signature: "Transfer(address,address,uint256)",
inputs: [
{ name: "from", type: "address", indexed: true },
{ name: "to", type: "address", indexed: true },
{ name: "value", type: "uint256", indexed: false },
],
topics: [topic0, "0x…", "0x…"],
data: "0x…",
})
// Walk a batch of logs from `eth_getLogs`
const decoded = decode_logs(events_abi, raw_logs)Compose codecs by hand — make_codec and the primitives
When the call shape varies at runtime (a registry that holds heterogeneous types), build the codec from primitive AbiCodec<T> instances.
import {
type AbiCodec,
address, bool, bytes, bytes4, bytes32,
string_, uint256, hash32,
array, tuple,
encode_sequence, decode_sequence,
make_codec,
} from "@ethernauta/abi"
const codec = tuple({ to: address(), value: uint256() })
const packed = encode_sequence([codec], [{ to: "0x…", value: 1n }])
const [decoded] = decode_sequence([codec], packed)
// `make_codec("uint256")` returns the primitive by Solidity name
const dynamic = make_codec("address")uint256 also exposes raw width helpers — read_uint256 / write_uint256 for tight loops that bypass the AbiCodec envelope.
Parse and walk an ABI
import {
parse_abi,
type Description,
DescriptionSchema,
} from "@ethernauta/abi"
const descriptions = parse_abi(ERC20_ABI)
// Description = function | constructor | fallback | receive | event | errorGenerate methods programmatically
import {
type Description,
DescriptionSchema,
emit_name_for,
emit_file_basename_for,
generate,
} from "@ethernauta/abi/generator"
import { array, parse } from "valibot"
const descriptions = parse(array(DescriptionSchema), ERC721_ABI)
const functions = descriptions.filter(
(description): description is Description => description.type === "function",
)
generate(functions, "app") // methods will be generated at "app/methods"
// Pure name helpers (the same ones the generator uses internally)
const fn_name = emit_name_for("transferFrom") // "transferFrom"
const file_name = emit_file_basename_for("transferFrom") // "transfer-from"Generate methods via the CLI
npx ethernauta abi --in abis/IERC20.abi.json --out app/methodsSee @ethernauta/cli for the full CLI reference.
