> ## 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.

# WASM

> WebAssembly compilation, build modes, and browser integration

# WASM

Voltaire compiles to WebAssembly for browser and non-Bun JavaScript runtimes.

<Tip>
  Runtime support: In <strong>Node.js</strong>, use the regular TypeScript API or <strong>WASM</strong>. Native FFI is currently <strong>Bun-only</strong>.
</Tip>

## Build Modes

### ReleaseSmall (Default)

Size-optimized for production bundles:

```bash theme={null}
zig build build-ts-wasm
```

* Output: `wasm/primitives.wasm` (\~385KB)
* Optimized for bundle size
* Suitable for browser deployment

### ReleaseFast

Performance-optimized for benchmarking:

```bash theme={null}
zig build build-ts-wasm-fast
```

* Output: `wasm/primitives-fast.wasm` (\~500KB)
* Maximum performance
* Use for performance-critical applications

### Individual Crypto Modules

Tree-shakeable individual modules:

```bash theme={null}
zig build crypto-wasm
```

Output in `wasm/crypto/`:

* `keccak256.wasm` (\~50KB)
* `secp256k1.wasm` (\~80KB)
* `blake2.wasm` (\~40KB)
* `ripemd160.wasm` (\~30KB)
* `bn254.wasm` (\~100KB)

## WASM Loader

The loader handles instantiation, memory management, and error translation.

### Location

```
src/wasm-loader/
├── loader.ts           # Main loader
├── memory.ts           # Memory management
├── errors.ts           # Error translation
└── types.ts            # TypeScript types
```

### Usage

```typescript theme={null}
import { loadWasm, getWasm } from "@voltaire/wasm-loader";

// Initialize (async, once at startup)
await loadWasm();

// Get WASM instance (sync, after initialization)
const wasm = getWasm();

// Use WASM functions
const hash = wasm.keccak256(data);
```

### Automatic Loading

Most functions auto-load WASM on first use:

```typescript theme={null}
import * as Keccak256 from "@voltaire/crypto/Keccak256";

// First call loads WASM automatically
const hash = await Keccak256.hash("hello");

// Subsequent calls are sync
const hash2 = Keccak256.hash("world");
```

## Memory Management

### How It Works

1. TypeScript passes data to WASM memory
2. WASM processes in its linear memory
3. Results copied back to JavaScript

```typescript theme={null}
// Internal flow (simplified)
function wasmHash(data: Uint8Array): Uint8Array {
  // Allocate WASM memory
  const inputPtr = wasm.alloc(data.length);
  const outputPtr = wasm.alloc(32);

  // Copy input to WASM
  new Uint8Array(wasm.memory.buffer, inputPtr, data.length).set(data);

  // Call WASM function
  wasm.keccak256(inputPtr, data.length, outputPtr);

  // Copy result from WASM
  const result = new Uint8Array(32);
  result.set(new Uint8Array(wasm.memory.buffer, outputPtr, 32));

  // Free WASM memory
  wasm.free(inputPtr);
  wasm.free(outputPtr);

  return result;
}
```

### Memory Limits

Default WASM memory: 256 pages (16MB)

For large operations, memory grows automatically:

```typescript theme={null}
// Handles large blobs transparently
const bigData = new Uint8Array(10_000_000);
const hash = Keccak256.hash(bigData);  // Memory grows as needed
```

## Platform Detection

The library automatically selects the best implementation:

```typescript theme={null}
// Internal detection
function getImplementation() {
  if (typeof Bun !== "undefined") {
    return "native";  // Bun FFI
  }
  if (typeof window !== "undefined" || typeof self !== "undefined") {
    return "wasm";    // Browser
  }
  if (typeof process !== "undefined") {
    return "wasm";    // Node.js
  }
  return "wasm";      // Fallback
}
```

### Forcing WASM

```typescript theme={null}
import * as Keccak256 from "@voltaire/crypto/Keccak256/wasm";

// Always uses WASM, even in Bun
const hash = Keccak256.hash("hello");
```

## Limitations

### KZG Not Supported

KZG operations require the trusted setup and are too large for WASM:

```typescript theme={null}
import * as Kzg from "@voltaire/crypto/Kzg";

// In WASM environment
try {
  const commitment = Kzg.blobToCommitment(blob);
} catch (e) {
  // Error: KZG not supported in WASM
}
```

<Tip>
  For KZG in browsers, use a server-side proxy or the c-kzg-4844 JS library.
</Tip>

### No Assembly Optimization

WASM can't use platform-specific assembly. Rust crypto uses `portable` feature:

```toml theme={null}
# Cargo.toml
[features]
default = ["asm"]        # Native: keccak-asm
portable = ["tiny-keccak"]  # WASM: pure Rust
```

Performance difference:

* Native (asm): \~500ns per Keccak256
* WASM: \~2μs per Keccak256

## Browser Integration

### Bundler Setup

#### Vite

```typescript theme={null}
// vite.config.ts
export default {
  optimizeDeps: {
    exclude: ["@voltaire/primitives"]
  },
  build: {
    target: "esnext"
  }
};
```

#### Webpack

```javascript theme={null}
// webpack.config.js
module.exports = {
  experiments: {
    asyncWebAssembly: true
  },
  module: {
    rules: [
      {
        test: /\.wasm$/,
        type: "webassembly/async"
      }
    ]
  }
};
```

### CDN Usage

```html theme={null}
<script type="module">
  import { loadWasm } from "https://esm.sh/@voltaire/primitives";
  import * as Address from "https://esm.sh/@voltaire/primitives/Address";

  await loadWasm();

  const addr = Address.fromHex("0x742d35Cc6634C0532925a3b844Bc9e7595f251e3");
  console.log(Address.toChecksummed(addr));
</script>
```

## Testing WASM

### Separate Test Files

```typescript theme={null}
// Keccak256.wasm.test.ts
import { describe, it, expect, beforeAll } from "vitest";
import { loadWasm } from "../wasm-loader/loader.js";
import * as Keccak256 from "./Keccak256.wasm.js";

describe("Keccak256 WASM", () => {
  beforeAll(async () => {
    await loadWasm();
  });

  it("hashes correctly", () => {
    const result = Keccak256.hash("hello");
    expect(result.length).toBe(32);
  });
});
```

### Running WASM Tests

```bash theme={null}
# All WASM tests
bun run test:wasm

# Specific module
bun run test:wasm -- Keccak256
```

### Cross-Validation

```typescript theme={null}
describe("WASM matches native", () => {
  it("produces identical results", () => {
    const data = "test data";

    const wasmResult = Keccak256Wasm.hash(data);
    const nativeResult = Keccak256Native.hash(data);

    expect(wasmResult).toEqual(nativeResult);
  });
});
```

## Bundle Size Analysis

```bash theme={null}
# Analyze bundle sizes
bun run size
```

Output in `BUNDLE-SIZES.md`:

```
| Module | Size | Gzipped |
|--------|------|---------|
| primitives.wasm | 385KB | 120KB |
| crypto/keccak256.wasm | 50KB | 18KB |
| crypto/secp256k1.wasm | 80KB | 28KB |
```

## Performance Comparison

```bash theme={null}
# Compare WASM modes
bun run scripts/compare-wasm-modes.ts
```

Typical results:

| Operation        | ReleaseSmall | ReleaseFast | Native |
| ---------------- | ------------ | ----------- | ------ |
| Keccak256        | 2.1μs        | 1.8μs       | 0.5μs  |
| secp256k1 sign   | 150μs        | 120μs       | 50μs   |
| Address checksum | 1.5μs        | 1.2μs       | 0.3μs  |

## Troubleshooting

### WASM Not Loading

```typescript theme={null}
// Check if WASM is available
import { isWasmLoaded, loadWasm } from "@voltaire/wasm-loader";

if (!isWasmLoaded()) {
  try {
    await loadWasm();
  } catch (e) {
    console.error("WASM failed to load:", e);
    // Fallback to JS implementation
  }
}
```

### Memory Errors

```typescript theme={null}
// For very large operations
import { setMemoryLimit } from "@voltaire/wasm-loader";

// Increase to 64MB (4096 pages)
setMemoryLimit(4096);

// Now process large data
const hugeBlob = new Uint8Array(50_000_000);
const hash = Keccak256.hash(hugeBlob);
```

### Build Issues

```bash theme={null}
# Verify WASI support
zig targets | grep wasm32-wasi

# Clean rebuild
zig build clean
zig build build-ts-wasm

# Check output
ls -la wasm/
```
