Skip to main content
Voltaire provides three implementation tiers for performance-critical operations. Choose based on your runtime environment and performance needs.

Three Tiers

TierImportRuntimeUse Case
TypeScript@tevm/voltaireAny JS runtimeDefault, universal compatibility
WASM@tevm/voltaire/wasmBrowser, Node, Bun, DenoHigh performance, portable
Native@tevm/voltaire/nativeBunMaximum performance via FFI
All three tiers expose identical APIs. Swap implementations without changing your code.

TypeScript (Default)

Pure TypeScript with zero dependencies. Works everywhere JavaScript runs.
import { Keccak256, Address, Hex } from '@tevm/voltaire'

// Keccak256.hash expects Uint8Array, Hex.fromString returns hex string
const hash = Keccak256.hash(Hex.toBytes(Hex.fromString('hello')))
const addr = Address.from('0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e')
Best for:
  • Universal browser/server compatibility
  • Debugging and development
  • Bundle size sensitive applications
  • Environments without WASM support

WASM

WebAssembly bindings to Zig implementations. Portable high-performance.
import * as wasm from '@tevm/voltaire/wasm'

// Crypto operations
const hash = wasm.keccak256(data)
const recovered = wasm.secp256k1RecoverAddress(hash, signature)

// Primitives
const bytes = wasm.hexToBytes('0xdeadbeef')
const hex = wasm.bytesToHex(bytes)

// Full namespaces
wasm.Secp256k1Wasm.sign(message, privateKey)
wasm.Blake2Wasm.hash(data)
wasm.Sha256Wasm.hash(data)
Available WASM modules:
  • Crypto: Keccak256, Secp256k1, SHA256, RIPEMD160, Blake2, Ed25519, X25519, P256
  • Primitives: Hex, RLP, U256, Blob, AccessList, Transaction, Bytecode
Best for:
  • Browser applications needing crypto performance
  • Serverless/edge functions (Cloudflare Workers, Vercel Edge)
  • Cross-platform consistency

Native FFI (Bun)

Direct bindings to Zig via Bun FFI. Maximum performance.
import * as native from '@tevm/voltaire/native'

// Check runtime
native.isBun()   // true in Bun
native.isNode()  // true in Node.js

// Keccak256 (async - lazy loads native lib)
const hash = await native.Keccak256.hash(data)
const selector = await native.Keccak256.selector('transfer(address,uint256)')

// Sync after initial load
const hash2 = native.Keccak256.hashSync(data)
Runtime support: Native FFI is Bun-only right now. In Node.js, use the regular TypeScript API or the WASM modules. Also ensure the compiled .dylib/.so/.dll is available (run zig build build-ts-native).
Best for:
  • Server-side applications with heavy crypto workloads
  • CLI tools
  • Maximum throughput requirements

Per-Module Imports

For fine-grained control, import specific implementations:
// Keccak256 variants
import * as Keccak256 from '@tevm/voltaire/Keccak256'           // Default (TS)
import * as Keccak256 from '@tevm/voltaire/Keccak256/native'    // Native FFI
import * as Keccak256 from '@tevm/voltaire/Keccak256/wasm'      // WASM

Performance Considerations

Performance is nuanced. WASM/Native aren’t always faster than TypeScript.
Bridging overhead: Crossing the JS↔WASM or JS↔FFI boundary has constant overhead (~1-10μs). For cheap operations (simple math, short string manipulation), this overhead can exceed the operation itself. When WASM/Native wins:
  • Cryptographic operations (keccak256, secp256k1, BLS) - 5-15x faster
  • Large data encoding/decoding (RLP, ABI with big payloads)
  • Batch operations that amortize bridging cost
When TypeScript wins:
  • Simple operations (hex encoding small values, address validation)
  • Single-item operations with low computational cost
  • When avoiding async overhead matters (native FFI is async on first load)
Bundle size: For cryptography specifically, WASM is often smaller than equivalent pure-JS implementations. A full JS secp256k1 library can be 50-100KB, while WASM crypto modules are typically 20-40KB.
OperationTypeScriptWASMNativeDefault
keccak2561x~5x~10xTypeScript
secp256k1 sign1x~8x~15xTypeScript
secp256k1 recover1x~8x~15xTypeScript
RLP encode1x~1.2x~1.5xTypeScript
Hex encode1x~1.1x~1.2xTypeScript
Benchmark your actual workload. Default implementations are chosen for common use cases, but your specific access patterns may differ.

WASM Limitations

Some cryptographic modules require native C/Rust libraries and are not available in WASM. These modules will return errors when called from the WASM entrypoint.
ModuleWASM StatusReasonAlternative
BLS12-381❌ Not availableRequires BLST (C library)Use native entrypoint
BN254 (arkworks)❌ Not availableRequires Rust FFIPure Zig bn254 works in WASM
KZG❌ Not availableRequires c-kzg-4844 (C library)Use native entrypoint
BIP-39 / HD Wallet❌ Not availableRequires libwally-core (C library)Use native or JS entrypoint
Calling unavailable modules in WASM returns error.NotSupported or equivalent errors. Check your target environment before using these modules.
What works in WASM:
  • All primitives (Address, Hex, Uint, Hash, RLP, ABI, etc.)
  • Keccak256, SHA256, RIPEMD160, Blake2
  • secp256k1, Ed25519, P256, X25519
  • Pure Zig BN254 implementation (not arkworks)
  • ChaCha20-Poly1305, AES-GCM
  • EIP-712 typed data signing