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
Direct Import
Selective Import
// 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 ( 50 n )
const wei = Gwei . toWei ( gwei ) // Uses WASM acceleration
const ether = Wei . toEther ( wei ) // Uses WASM acceleration
import * as Wei from 'tevm/Wei'
import * as WeiWasm from 'tevm/Wei.wasm'
// Override specific methods with WASM versions
const weiToGwei = WeiWasm . toGwei
const weiToEther = WeiWasm . toEther
// Use WASM versions
const wei = Wei ( 1_000_000_000 n )
const gwei = weiToGwei ( wei )
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_000 n )
// 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 ( 50 n )
// 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 ( 1 n )
// 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 ( 10 n ),
GweiWasm ( 30 n ),
GweiWasm ( 50 n ),
GweiWasm ( 100 n ),
]
const gasUsed = Uint ( 21_000 n )
// 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_000 n ),
WeiWasm ( 2_500_000_000_000_000_000 n ),
WeiWasm ( 500_000_000_000_000_000 n ),
]
// 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 ,
}
}
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 ( 50 n )
// 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