Documentation Index
Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
Use this file to discover all available pages before exploring further.
API Conventions
Consistent API design across all modules.
Naming Conventions
Constructors
| Pattern | Usage | Example |
|---|
Type(value) | Primary constructor | Address("0x...") |
Type.from(value) | Explicit variant | Address.from("0x...") |
Type.fromX(value) | From specific type | Address.fromHex("0x...") |
// ✅ Preferred - direct call
const addr = Address("0x742d35Cc6634C0532925a3b844Bc9e7595f251e3");
// ✅ Also valid - explicit
const addr = Address.from("0x742d35Cc6634C0532925a3b844Bc9e7595f251e3");
// ✅ Specific format
const addr = Address.fromHex("0x742d35Cc6634C0532925a3b844Bc9e7595f251e3");
const addr = Address.fromBytes(bytes);
const addr = Address.fromPublicKey(pubkey);
Converters
| Pattern | Usage | Example |
|---|
Type.toX(value) | Convert to X | Address.toHex(addr) |
Type.asX(value) | View as X (no copy) | Uint256.asBigInt(uint) |
// Convert (may allocate)
const hex = Address.toHex(addr);
const bytes = Address.toBytes(addr);
const checksummed = Address.toChecksummed(addr);
// View (no allocation, same underlying data)
const bigint = Uint256.asBigInt(uint);
Predicates
| Pattern | Usage | Returns |
|---|
Type.is(value) | Type guard | value is Type |
Type.isValid(value) | Validation | boolean |
Type.isX(value) | Specific check | boolean |
// Type guard - narrows type
if (Address.is(value)) {
// value is Address here
}
// Validation - just boolean
if (Address.isValid(input)) {
const addr = Address(input); // Safe to construct
}
// Specific checks
if (Address.isChecksum(addr)) { ... }
if (Address.isZero(addr)) { ... }
Comparisons
| Pattern | Usage |
|---|
Type.equals(a, b) | Equality check |
Type.compare(a, b) | Ordering (-1, 0, 1) |
Type.lt(a, b) | Less than |
Type.gt(a, b) | Greater than |
// Equality
Address.equals(a, b); // true/false
// Ordering (for sortable types)
Uint256.compare(a, b); // -1, 0, or 1
Uint256.lt(a, b); // a < b
Uint256.gt(a, b); // a > b
Function Signatures
Public functions accept flexible inputs:
// Public API - accepts various inputs
export function toHex(value: AddressInput): Hex {
return _toHex(from(value)); // Converts internally
}
// AddressInput = Address | Hex | Uint8Array | `0x${string}`
Internal Functions
Internal functions require exact types:
// Internal - requires branded type
export function _toHex(address: Address): Hex {
// No conversion needed
}
Naming Convention
// Public wrapper (flexible input)
export function toHex(value: AddressInput): Hex;
// Internal (strict input, underscore prefix)
export function _toHex(address: Address): Hex;
Error Handling
Error Types
Each module defines its own error class:
// primitives/Address/errors.ts
export class InvalidAddressError extends Error {
readonly name = "InvalidAddressError";
constructor(value: unknown) {
super(`Invalid address: ${formatValue(value)}`);
}
}
export class ChecksumMismatchError extends Error {
readonly name = "ChecksumMismatchError";
constructor(expected: string, actual: string) {
super(`Checksum mismatch: expected ${expected}, got ${actual}`);
}
}
When to Throw
// ✅ Throw on invalid input
export function fromHex(hex: string): Address {
if (!isValidHex(hex)) {
throw new InvalidAddressError(hex);
}
// ...
}
// ✅ Return boolean for validation
export function isValid(value: unknown): boolean {
// Never throws
return typeof value === "string" && isValidHex(value);
}
// ✅ Return null for "try" variants
export function tryFromHex(hex: string): Address | null {
if (!isValid(hex)) return null;
return fromHex(hex);
}
Error Messages
// ✅ Clear, actionable message
throw new InvalidAddressError("0x123");
// "Invalid address: 0x123"
// ✅ Truncate long values
throw new InvalidAddressError(veryLongString);
// "Invalid address: 0x742d35Cc6634C0532925a3b8... (truncated)"
// ❌ Vague message
throw new Error("Invalid input");
// ❌ Technical jargon
throw new Error("EIP-55 checksum validation failed for mixed-case input");
Return Types
Branded Types
Always return branded types, not plain arrays:
// ✅ Returns branded type
export function fromHex(hex: string): Address {
// ...
return bytes as Address;
}
// ❌ Returns plain Uint8Array
export function fromHex(hex: string): Uint8Array {
// Loses type safety
}
Immutability
Returned values should be treated as immutable:
const addr = Address.fromHex("0x...");
// ❌ Don't mutate
addr[0] = 0x00; // Type system doesn't prevent this, but don't do it
// ✅ Create new if needed
const modified = new Uint8Array(addr);
modified[0] = 0x00;
Documentation
JSDoc for .js Files
// toHex.js
/**
* Convert address to checksummed hex string.
*
* @param {import('./AddressType.js').Address} address - The address to convert
* @returns {string} EIP-55 checksummed hex string
* @throws {TypeError} If address is not a valid Address
*
* @example
* const hex = toHex(address);
* // "0x742d35Cc6634C0532925a3b844Bc9e7595f251e3"
*/
export function toHex(address) {
// ...
}
TypeScript Types in index.ts
// index.ts
/**
* Convert address to checksummed hex string
*
* @example
* ```ts
* import * as Address from "@voltaire/primitives/Address";
*
* const hex = Address.toHex("0x742d35cc6634c0532925a3b844bc9e7595f251e3");
* // "0x742d35Cc6634C0532925a3b844Bc9e7595f251e3"
* ```
*/
export function toHex(value: AddressInput): string {
return _toHex(from(value));
}
Constants
Named Constants
// constants.ts
export const ZERO_ADDRESS = Address(new Uint8Array(20));
export const MAX_ADDRESS = Address(new Uint8Array(20).fill(0xff));
// Precompile addresses
export const ECRECOVER_ADDRESS = Address.fromHex("0x0000000000000000000000000000000000000001");
export const SHA256_ADDRESS = Address.fromHex("0x0000000000000000000000000000000000000002");
Export in Index
// index.ts
export { ZERO_ADDRESS, MAX_ADDRESS } from "./constants.js";
Module Structure
Standard Exports
Every primitive module exports:
// Type
export type { Address } from "./AddressType.js";
// Constructors
export { from } from "./from.js";
export { from as Address } from "./from.js";
export { fromHex } from "./fromHex.js";
export { fromBytes } from "./fromBytes.js";
// Internal methods
export { toHex as _toHex } from "./toHex.js";
export { equals as _equals } from "./equals.js";
// Public wrappers
export function toHex(value: AddressInput): string { ... }
export function equals(a: AddressInput, b: AddressInput): boolean { ... }
// Predicates
export { is } from "./is.js";
export { isValid } from "./isValid.js";
// Constants
export { ZERO_ADDRESS } from "./constants.js";
Namespace Usage
// User imports as namespace
import * as Address from "@voltaire/primitives/Address";
// All functions available
Address.fromHex("0x...");
Address.toHex(addr);
Address.equals(a, b);
Address.isValid(input);
Address.ZERO_ADDRESS;
Async Conventions
Sync by Default
Most functions are synchronous:
// ✅ Sync - no I/O needed
export function hash(data: Uint8Array): Uint8Array { ... }
export function verify(sig: Signature): boolean { ... }
Async When Required
Use async only for I/O:
// ✅ Async - requires network
export async function fetchAddress(name: string): Promise<Address> {
const response = await fetch(`https://api.ens.domains/${name}`);
// ...
}
// ✅ Async - WASM loading
export async function loadWasm(): Promise<void> {
await WebAssembly.instantiate(wasmBytes);
}
Naming for Async
// Sync version
export function hash(data: Uint8Array): Uint8Array;
// Async version (when both exist)
export async function hashAsync(data: Uint8Array): Promise<Uint8Array>;