Skip to main content

Try it Live

Run Denomination examples in the interactive playground

WASM Implementation

WebAssembly-accelerated implementations of denomination conversions, compiled from Zig using ReleaseSmall mode.

Overview

WASM implementations provide performance-critical denomination operations using compiled Zig code targeting WebAssembly. These are purely opt-in replacements for the JavaScript implementations with identical APIs. All WASM methods are compiled from denomination.zig with ReleaseSmall optimization targeting minimal bundle size.

Quick Start

// Import WASM implementation instead of JS version
import * as Wei from 'tevm/Wei.wasm'
import * as Gwei from 'tevm/Gwei.wasm'
import * as Ether from 'tevm/Ether.wasm'

// API is identical to JS version
const gwei = Gwei(50n)
const wei = Gwei.toWei(gwei)  // Uses WASM acceleration
const ether = Wei.toEther(wei)  // Uses WASM acceleration

Performance

WASM implementations provide significant speedup for:
  • U256 arithmetic - Compiled Zig multiplication and division
  • Bulk conversions - Processing many values in tight loops
  • Constant-time operations - No JavaScript overhead
Use WASM when processing many denomination conversions (gas calculations, bulk balance conversions). For single operations, JS overhead may outweigh WASM benefits.

API Reference

WASM implementations match the standard Denomination API. See main documentation:
  • Wei - from, fromGwei, fromEther, toGwei, toEther, toU256
  • Gwei - from, fromWei, fromEther, toWei, toEther, toU256
  • Ether - from, fromWei, fromGwei, toWei, toGwei, toU256

WASM-Accelerated Methods

All denomination conversions implemented in Zig:

Wei

import * as WeiWasm from 'tevm/Wei.wasm'

// Construction
const wei = WeiWasm(1_000_000_000n)

// Conversions
const gwei = WeiWasm.toGwei(wei)      // Wei → Gwei (division)
const ether = WeiWasm.toEther(wei)    // Wei → Ether (division)
const u256 = WeiWasm.toU256(wei)      // Wei → Uint256 (unwrap)

// From other units
const wei2 = WeiWasm.fromGwei(gwei)   // Gwei → Wei (multiplication)
const wei3 = WeiWasm.fromEther(ether) // Ether → Wei (multiplication)

Gwei

import * as GweiWasm from 'tevm/Gwei.wasm'

// Construction
const gwei = GweiWasm(50n)

// Conversions
const wei = GweiWasm.toWei(gwei)      // Gwei → Wei (multiplication)
const ether = GweiWasm.toEther(gwei)  // Gwei → Ether (division)
const u256 = GweiWasm.toU256(gwei)    // Gwei → Uint256 (unwrap)

// From other units
const gwei2 = GweiWasm.fromWei(wei)   // Wei → Gwei (division)
const gwei3 = GweiWasm.fromEther(ether) // Ether → Gwei (multiplication)

Ether

import * as EtherWasm from 'tevm/Ether.wasm'

// Construction
const ether = EtherWasm(1n)

// Conversions
const wei = EtherWasm.toWei(ether)    // Ether → Wei (multiplication)
const gwei = EtherWasm.toGwei(ether)  // Ether → Gwei (multiplication)
const u256 = EtherWasm.toU256(ether)  // Ether → Uint256 (unwrap)

// From other units
const ether2 = EtherWasm.fromWei(wei)   // Wei → Ether (division)
const ether3 = EtherWasm.fromGwei(gwei) // Gwei → Ether (division)

Usage Examples

Bulk Gas Calculations

import * as GweiWasm from 'tevm/Gwei.wasm'
import * as Uint from 'tevm/Uint'

const gasPrices = [
  GweiWasm(10n),
  GweiWasm(30n),
  GweiWasm(50n),
  GweiWasm(100n),
]

const gasUsed = Uint(21_000n)

// Process all in WASM (faster for bulk operations)
const costs = gasPrices.map(price => {
  const priceWei = GweiWasm.toWei(price)
  return Uint.times(priceWei, gasUsed)
})

Balance Conversions

import * as WeiWasm from 'tevm/Wei.wasm'

const balancesWei = [
  WeiWasm(1_000_000_000_000_000_000n),
  WeiWasm(2_500_000_000_000_000_000n),
  WeiWasm(500_000_000_000_000_000n),
]

// Convert all to Ether using WASM
const balancesEther = balancesWei.map(WeiWasm.toEther)

Real-Time Gas Price Tracking

import * as GweiWasm from 'tevm/Gwei.wasm'
import * as WeiWasm from 'tevm/Wei.wasm'

interface GasEstimate {
  fast: bigint
  standard: bigint
  slow: bigint
}

function estimateCost(
  estimate: GasEstimate,
  gasUsed: bigint
): GasEstimate {
  // Convert all Gwei prices to Wei costs using WASM
  const fast = GweiWasm.toWei(GweiWasm(estimate.fast))
  const standard = GweiWasm.toWei(GweiWasm(estimate.standard))
  const slow = GweiWasm.toWei(GweiWasm(estimate.slow))

  return {
    fast: fast * gasUsed,
    standard: standard * gasUsed,
    slow: slow * gasUsed,
  }
}

Performance Characteristics

Multiplication (Upscaling)

Conversions that multiply are memory-bound:
  • Gwei.toWei - multiply by 10^9
  • Ether.toWei - multiply by 10^18
  • Ether.toGwei - multiply by 10^9
WASM benefit: Moderate (10-30% faster) - limited by memory access.

Division (Downscaling)

Conversions that divide are compute-bound:
  • Wei.toGwei - divide by 10^9
  • Wei.toEther - divide by 10^18
  • Gwei.toEther - divide by 10^9
WASM benefit: Significant (2-5x faster) - Zig division highly optimized.

Files

  • denomination.zig - Zig source implementation
  • Wei.wasm.ts - TypeScript WASM bindings for Wei
  • Gwei.wasm.ts - TypeScript WASM bindings for Gwei
  • Ether.wasm.ts - TypeScript WASM bindings for Ether

Zig Tests

The Zig implementation includes comprehensive tests:
test "wei to gwei conversion" {
    const w = Wei.from_u256(U256.from_u64(1_000_000_000))
    const g = w.to_gwei()
    try testing.expect(g.value.eq(U256.from_u64(1)))
}

test "wei to ether conversion" {
    const limbs: [4]u64 = .{ 0xde0b6b3a7640000, 0, 0, 0 }
    const w = Wei.from_u256(U256.from_limbs(limbs))
    const e = w.to_ether()
    try testing.expect(e.value.eq(U256.from_u64(1)))
}

test "round trip conversions" {
    const original = Wei.from_u256(U256.from_u64(5_000_000_000))
    const g = original.to_gwei()
    const back = g.to_wei()
    try testing.expect(back.value.eq(U256.from_u64(5_000_000_000)))
}
Run tests:
zig build test -Dtest-filter="denomination"

Benchmarking

Compare JS vs WASM performance:
import * as Gwei from 'tevm/Gwei'
import * as GweiWasm from 'tevm/Gwei.wasm'

const iterations = 100_000
const gwei = Gwei(50n)

// Benchmark JS
console.time('JS')
for (let i = 0; i < iterations; i++) {
  Gwei.toWei(gwei)
}
console.timeEnd('JS')

// Benchmark WASM
console.time('WASM')
for (let i = 0; i < iterations; i++) {
  GweiWasm.toWei(gwei)
}
console.timeEnd('WASM')

Limitations

WASM implementations have same behavior as JS:
  • Integer division - Fractional results truncate
  • No overflow checks - U256 operations wrap
  • Same API - Drop-in replacement
  • Wei - Wei API reference
  • Gwei - Gwei API reference
  • Ether - Ether API reference
  • Conversions - Conversion details
  • Uint WASM - Underlying U256 WASM implementation