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.
CallData operations can be accelerated using WebAssembly for performance-critical applications. The Zig implementation compiles to WASM, providing near-native speed in browser and Node.js environments.
Build Modes
Voltaire provides two WASM build modes optimized for different use cases:
ReleaseSmall (Production)
Size-optimized build for production bundles:
Characteristics:
- Minimal bundle size (~50-100KB compressed)
- Aggressive dead code elimination
- Optimized for download speed
- Suitable for web applications
Performance-optimized build for compute-intensive workloads:
Characteristics:
- Maximum execution speed
- Larger binary size (~150-300KB compressed)
- Loop unrolling and inlining
- Suitable for backend services, workers
Encoding
Decoding
Selector Matching
Encoding function call with parameters:import { CallData, Abi, Address, TokenBalance } from '@tevm/voltaire';
const abi = Abi([{
name: "transfer",
type: "function",
inputs: [
{ name: "to", type: "address" },
{ name: "amount", type: "uint256" }
]
}]);
const recipient = Address("0x70997970C51812dc3A010C7d01b50e0d17dc79C8");
const amount = TokenBalance.fromUnits("1000", 18);
// Benchmark
console.time("encode");
const calldata = abi.transfer.encode(recipient, amount);
console.timeEnd("encode");
Results (1M iterations):
- Pure JS: ~850ms
- WASM (ReleaseSmall): ~320ms (2.6x faster)
- WASM (ReleaseFast): ~180ms (4.7x faster)
Decoding calldata to structured form:const calldata = CallData("0xa9059cbb...");
console.time("decode");
const decoded = CallData.decode(calldata, abi);
console.timeEnd("decode");
Results (1M iterations):
- Pure JS: ~920ms
- WASM (ReleaseSmall): ~380ms (2.4x faster)
- WASM (ReleaseFast): ~210ms (4.4x faster)
Extracting and matching function selectors:console.time("selector");
const selector = CallData.getSelector(calldata);
const isTransfer = CallData.hasSelector(calldata, "0xa9059cbb");
console.timeEnd("selector");
Results (10M iterations):
- Pure JS: ~450ms
- WASM (ReleaseSmall): ~120ms (3.8x faster)
- WASM (ReleaseFast): ~65ms (6.9x faster)
Usage
Automatic Selection
Voltaire automatically uses WASM when available:
import { CallData } from '@tevm/voltaire';
// Automatically uses WASM if loaded
const calldata = CallData("0xa9059cbb...");
const selector = CallData.getSelector(calldata);
No code changes needed - WASM acceleration is transparent.
Manual Loading
For advanced control, manually load WASM module:
import { loadWasm } from '@tevm/voltaire/wasm-loader';
import { CallData } from '@tevm/voltaire';
// Load WASM module
await loadWasm('primitives');
// Now using WASM acceleration
const calldata = CallData.encode("transfer(address,uint256)", [addr, amount]);
import { loadWasm } from '@tevm/voltaire/wasm-loader';
// Load from CDN or local path
await loadWasm('primitives', {
url: '/wasm/primitives.wasm'
});
// WASM now active for all CallData operations
// worker.ts
import { loadWasm } from '@tevm/voltaire/wasm-loader';
import { CallData } from '@tevm/voltaire';
// Load WASM in worker context
await loadWasm('primitives-fast'); // Use fast build
// Handle messages
self.onmessage = async (e) => {
const { signature, params } = e.data;
const calldata = CallData.encode(signature, params);
self.postMessage({ calldata: CallData.toHex(calldata) });
};
Checking WASM Status
Verify if WASM is loaded:
import { isWasmLoaded } from '@tevm/voltaire/wasm-loader';
if (isWasmLoaded('primitives')) {
console.log('Using WASM acceleration');
} else {
console.log('Falling back to pure JS');
}
Memory Management
WASM module manages its own memory efficiently:
Linear Memory
WASM uses linear memory for all operations:
import { getWasmMemory } from '@tevm/voltaire/wasm-loader';
// Access WASM memory (advanced use only)
const memory = getWasmMemory('primitives');
console.log('Memory pages:', memory.buffer.byteLength / 65536);
Memory grows automatically when needed:
- Initial: 16 pages (1MB)
- Maximum: 256 pages (16MB)
- Growth: Automatic on demand
Allocation Strategy
Zig’s allocator optimizes for CallData operations:
// Internal implementation
pub fn encodeCallData(
allocator: std.mem.Allocator,
selector: [4]u8,
params: []const AbiValue,
) !CallData {
// Use arena allocator for batch operations
var arena = std.heap.ArenaAllocator.init(allocator);
defer arena.deinit();
// All allocations freed at once
const data = try encodeParams(arena.allocator(), params);
return CallData{ .data = data };
}
Benefits:
- Minimal fragmentation
- Batch deallocation
- Zero-cost cleanup
Memory Limits
Set memory limits for safety:
import { loadWasm } from '@tevm/voltaire/wasm-loader';
await loadWasm('primitives', {
memory: {
initial: 32, // 2MB
maximum: 512, // 32MB
}
});
Bundle Optimization
Tree-Shaking
Use tree-shakeable imports to minimize bundle size:
// Bundle includes only what you use
import { from, getSelector, toHex } from '@tevm/voltaire/CallData';
const calldata = from("0xa9059cbb...");
const selector = getSelector(calldata);
const hex = toHex(calldata);
// encode, decode, etc. excluded from bundle
Lazy Loading
Load WASM on demand to reduce initial bundle:
// Minimal initial bundle
import { CallData } from '@tevm/voltaire';
// Load WASM when needed
async function processCallData(data: string) {
const { loadWasm } = await import('tevm/wasm-loader');
await loadWasm('primitives');
return CallData.decode(CallData(data), abi);
}
Code Splitting
Split WASM by route/feature:
// route-1.ts - Only loads when route accessed
export async function handleRoute1() {
await import('tevm/wasm-loader').then(m => m.loadWasm('primitives'));
// Use CallData operations
}
// route-2.ts - Independent WASM loading
export async function handleRoute2() {
await import('tevm/wasm-loader').then(m => m.loadWasm('primitives'));
// Use CallData operations
}
Compatibility
WASM module works across platforms:
| Platform | Support | Notes |
|---|
| Chrome 57+ | ✅ Full | Native WASM support |
| Firefox 52+ | ✅ Full | Native WASM support |
| Safari 11+ | ✅ Full | Native WASM support |
| Edge 16+ | ✅ Full | Native WASM support |
| Node.js 12+ | ✅ Full | Built-in WASM runtime |
| Deno | ✅ Full | Native WASM support |
| Bun | ✅ Full | Optimized WASM JIT |
Fallback
Automatic fallback to pure JS when WASM unavailable:
import { CallData } from '@tevm/voltaire';
// Works everywhere - WASM when available, JS fallback otherwise
const calldata = CallData.encode("transfer(address,uint256)", [addr, amount]);
No polyfills or configuration needed.
Benchmarking
Write benchmarks to verify performance in your environment:
import { bench, run } from 'mitata';
import { CallData, Abi } from '@tevm/voltaire';
const abi = Abi([{
name: "transfer",
type: "function",
inputs: [
{ name: "to", type: "address" },
{ name: "amount", type: "uint256" }
]
}]);
bench('CallData.encode', () => {
abi.transfer.encode(
Address("0x70997970C51812dc3A010C7d01b50e0d17dc79C8"),
TokenBalance.fromUnits("1", 18)
);
});
bench('CallData.decode', () => {
CallData.decode(calldata, abi);
});
await run();
Debugging WASM
Enable Debug Logging
import { setWasmDebug } from '@tevm/voltaire/wasm-loader';
setWasmDebug(true);
// Now logs WASM operations:
// [WASM] Loading primitives.wasm
// [WASM] Memory allocated: 65536 bytes
// [WASM] Function called: encode_calldata
Inspect Module
import { getWasmModule } from '@tevm/voltaire/wasm-loader';
const module = getWasmModule('primitives');
console.log('Exports:', WebAssembly.Module.exports(module));
console.log('Imports:', WebAssembly.Module.imports(module));
Production Recommendations
- Use ReleaseSmall for web apps - Minimize download time
- Use ReleaseFast for compute - Backend services, workers
- Lazy load WASM - Don’t block initial page load
- Monitor memory - Set limits for long-running processes
- Test fallback - Ensure JS path works without WASM
See Also