Skip to main content
Voltaire primitives are designed to be identical across TypeScript, Zig, Swift, and Rust. The APIs match as closely as possible while respecting each language’s idioms.

Data-First Design

Every primitive is represented using the simplest possible data structure in each language:
LanguageAddress Representation
TypeScriptUint8Array (branded)
Zig[20]u8
SwiftData (20 bytes)
Rust[u8; 20]
No wrapper classes. No hidden state. Just bytes.

Functions Operate on Data

Methods take the data as the first parameter, similar to Go or Zig:
import { Address } from '@tevm/voltaire'

const addr = Address('0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e')
Address.toHex(addr)
Address.isZero(addr)
Address.equals(addr, other)

Why This Matters

Portable knowledge — Learn the API once, use it everywhere. A toHex in TypeScript works the same as toHex in Zig. LLM-friendly — AI assistants trained on one language can help with another. The patterns transfer directly. Predictable — No surprises when switching languages. Same function names, same parameter order, same behavior.

Language-Specific Conveniences

Each language adds idiomatic conveniences on top of the core API:
  • TypeScript: Instance methods (addr.toHex()) alongside static methods
  • Zig: Comptime validation and formatting
  • Swift: Protocol conformances (Equatable, Hashable, CustomStringConvertible)
These conveniences don’t change the underlying data or core function signatures.

Colocated Source Files

All language implementations live together in the same directory:
src/primitives/Address/
├── Address.zig      # Zig implementation
├── Address.swift    # Swift implementation
├── index.ts         # TypeScript implementation
├── toHex.js         # Shared JS function
├── toHex.zig        # Shared Zig function
└── ...
This makes it easy for both humans and LLMs to keep implementations in sync and see all versions of a function side-by-side.

Learn More