Skip to main content

Try it Live

Run Denomination examples in the interactive playground

Usage Patterns

Common patterns for working with Wei, Gwei, and Ether in real-world applications.

Gas Calculations

Basic Gas Cost

import * as Gwei from 'tevm/Gwei'
import * as Wei from 'tevm/Wei'
import * as Uint from 'tevm/Uint'

function calculateGasCost(
  gasPriceGwei: Gwei.Type,
  gasUsed: bigint
): Wei.Type {
  // Convert to Wei for calculation
  const gasPriceWei = Gwei.toWei(gasPriceGwei)

  // Calculate: gasPrice * gasUsed
  const cost = Uint.times(gasPriceWei, Uint(gasUsed))

  return Wei(cost)
}

// Example usage
const gasPrice = Gwei(50n)  // 50 Gwei
const gasUsed = 21_000n           // Standard transfer
const cost = calculateGasCost(gasPrice, gasUsed)

console.log(`Cost: ${cost} Wei`)  // 1_050_000_000_000_000 Wei
console.log(`Cost: ${Wei.toGwei(cost)} Gwei`)  // 1_050_000 Gwei

EIP-1559 Gas Calculation

import * as Gwei from 'tevm/Gwei'
import * as Wei from 'tevm/Wei'
import * as Uint from 'tevm/Uint'

interface EIP1559Params {
  baseFeePerGas: Gwei.Type
  maxPriorityFeePerGas: Gwei.Type
  maxFeePerGas: Gwei.Type
  gasLimit: bigint
}

function calculateEIP1559Cost(params: EIP1559Params): {
  maxCost: Wei.Type
  estimatedCost: Wei.Type
} {
  // Max possible cost
  const maxFeeWei = Gwei.toWei(params.maxFeePerGas)
  const maxCostU256 = Uint.times(maxFeeWei, Uint(params.gasLimit))

  // Estimated actual cost: baseFee + priorityFee
  const baseFeeU256 = Gwei.toU256(params.baseFeePerGas)
  const priorityFeeU256 = Gwei.toU256(params.maxPriorityFeePerGas)
  const effectiveFee = Uint.plus(baseFeeU256, priorityFeeU256)
  const effectiveFeeWei = Gwei.toWei(Gwei(effectiveFee))
  const estimatedCostU256 = Uint.times(effectiveFeeWei, Uint(params.gasLimit))

  return {
    maxCost: Wei(maxCostU256),
    estimatedCost: Wei(estimatedCostU256)
  }
}

// Example usage
const params: EIP1559Params = {
  baseFeePerGas: Gwei(30n),
  maxPriorityFeePerGas: Gwei(2n),
  maxFeePerGas: Gwei(50n),
  gasLimit: 21_000n
}

const { maxCost, estimatedCost } = calculateEIP1559Cost(params)
console.log(`Max: ${Wei.toEther(maxCost)} ETH`)
console.log(`Estimated: ${Wei.toEther(estimatedCost)} ETH`)

Gas Price Comparison

import * as Gwei from 'tevm/Gwei'
import * as Uint from 'tevm/Uint'

interface GasPrices {
  fast: Gwei.Type
  standard: Gwei.Type
  slow: Gwei.Type
}

function selectGasPrice(
  prices: GasPrices,
  maxPrice: Gwei.Type
): Gwei.Type | null {
  const maxU256 = Gwei.toU256(maxPrice)

  // Try fast first
  if (Gwei.toU256(prices.fast) <= maxU256) {
    return prices.fast
  }

  // Fall back to standard
  if (Gwei.toU256(prices.standard) <= maxU256) {
    return prices.standard
  }

  // Fall back to slow
  if (Gwei.toU256(prices.slow) <= maxU256) {
    return prices.slow
  }

  // All prices too high
  return null
}

// Example usage
const prices: GasPrices = {
  fast: Gwei(100n),
  standard: Gwei(50n),
  slow: Gwei(20n)
}

const maxPrice = Gwei(60n)
const selected = selectGasPrice(prices, maxPrice)

if (selected) {
  console.log(`Selected: ${selected} Gwei`)
} else {
  console.log('All prices exceed maximum')
}

Transaction Values

User Input to Transaction

import * as Ether from 'tevm/Ether'
import * as Wei from 'tevm/Wei'

function parseEtherInput(input: string): Wei.Type {
  // Parse user input (e.g., "1.5" ETH)
  const [whole, fractional = '0'] = input.split('.')

  // Convert to Wei manually to preserve fractional part
  const wholeBigInt = BigInt(whole)
  const fractionalPadded = fractional.padEnd(18, '0').slice(0, 18)
  const fractionalBigInt = BigInt(fractionalPadded)

  const wholeWei = Ether.toWei(Ether(wholeBigInt))
  const totalWei = Wei(Wei.toU256(wholeWei) + fractionalBigInt)

  return totalWei
}

// Example usage
const input = "1.5"  // User wants to send 1.5 ETH
const value = parseEtherInput(input)

const tx = {
  to: "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e",
  value: value,  // 1_500_000_000_000_000_000n Wei
}

console.log(`Sending ${value} Wei`)
console.log(`(${input} ETH)`)

Balance Checking

import * as Wei from 'tevm/Wei'
import * as Ether from 'tevm/Ether'
import * as Uint from 'tevm/Uint'

function hasSufficientBalance(
  balance: Wei.Type,
  value: Wei.Type,
  gasCost: Wei.Type
): boolean {
  const balanceU256 = Wei.toU256(balance)
  const valueU256 = Wei.toU256(value)
  const gasCostU256 = Wei.toU256(gasCost)

  // Total needed = value + gas
  const required = Uint.plus(valueU256, gasCostU256)

  return balanceU`256 >= required`
}

// Example usage
const balance = Wei(2_000_000_000_000_000_000n)  // 2 ETH
const value = Ether.toWei(Ether(1n))              // 1 ETH
const gasCost = Wei(50_000_000_000_000n)         // 0.00005 ETH

if (hasSufficientBalance(balance, value, gasCost)) {
  console.log('Sufficient balance')
} else {
  console.log('Insufficient balance')
}

Balance Display

Format Wei as Ether

import * as Wei from 'tevm/Wei'
import * as Uint from 'tevm/Uint'

function formatWeiAsEther(wei: Wei.Type, decimals: number = 18): string {
  const weiU256 = Wei.toU256(wei)
  const weiPerEther = Uint(1_000_000_000_000_000_000n)

  // Split into whole and fractional parts
  const wholePart = Uint.dividedBy(weiU256, weiPerEther)
  const fractionalPart = Uint.modulo(weiU256, weiPerEther)

  // Format fractional part with desired decimals
  const fractionalStr = fractionalPart.toString().padStart(18, '0')
  const truncated = fractionalStr.slice(0, decimals)

  // Remove trailing zeros
  const trimmed = truncated.replace(/0+$/, '') || '0'

  return `${wholePart}.${trimmed}`
}

// Example usage
const balance = Wei(1_234_567_890_123_456_789n)

console.log(formatWeiAsEther(balance, 18))  // "1.234567890123456789"
console.log(formatWeiAsEther(balance, 6))   // "1.234567"
console.log(formatWeiAsEther(balance, 2))   // "1.23"

Format with Units

import * as Wei from 'tevm/Wei'

function formatBalance(wei: Wei.Type): string {
  const weiU256 = Wei.toU256(wei)

  // `If >= 0`.01 ETH, show in ETH
  if (`weiU256 >= 10`_000_000_000_000_000n) {
    const ether = Wei.toEther(wei)
    return `${ether} ETH`
  }

  // `If >= 0`.00001 Gwei, show in Gwei
  if (`weiU256 >= 10`_000n) {
    const gwei = Wei.toGwei(wei)
    return `${gwei} Gwei`
  }

  // Otherwise show in Wei
  return `${wei} Wei`
}

// Example usage
console.log(formatBalance(Wei(1_000_000_000_000_000_000n)))  // "1 ETH"
console.log(formatBalance(Wei(50_000_000_000n)))             // "50 Gwei"
console.log(formatBalance(Wei(1_000n)))                      // "1000 Wei"

Compact Display

import * as Wei from 'tevm/Wei'
import * as Uint from 'tevm/Uint'

function formatCompact(wei: Wei.Type): string {
  const weiU256 = Wei.toU256(wei)
  const weiPerEther = Uint(1_000_000_000_000_000_000n)

  const wholePart = Uint.dividedBy(weiU256, weiPerEther)
  const fractionalPart = Uint.modulo(weiU256, weiPerEther)

  if (fractionalPart === 0n) {
    return `${wholePart} ETH`
  }

  // Show only significant decimals
  const fractionalStr = fractionalPart.toString().padStart(18, '0')
  const significant = fractionalStr.slice(0, 4)

  return `${wholePart}.${significant} ETH`
}

// Example usage
console.log(formatCompact(Wei(1_000_000_000_000_000_000n)))  // "1 ETH"
console.log(formatCompact(Wei(1_234_000_000_000_000_000n)))  // "1.2340 ETH"
console.log(formatCompact(Wei(500_000_000_000_000_000n)))    // "0.5000 ETH"

Arithmetic Operations

Adding Values

import * as Wei from 'tevm/Wei'
import * as Uint from 'tevm/Uint'

function addWei(a: Wei.Type, b: Wei.Type): Wei.Type {
  const aU256 = Wei.toU256(a)
  const bU256 = Wei.toU256(b)
  const sum = Uint.plus(aU256, bU256)
  return Wei(sum)
}

// Example usage
const balance1 = Wei(1_000_000_000_000_000_000n)  // 1 ETH
const balance2 = Wei(500_000_000_000_000_000n)     // 0.5 ETH
const total = addWei(balance1, balance2)                 // 1.5 ETH

console.log(`Total: ${total} Wei`)

Calculating Percentages

import * as Wei from 'tevm/Wei'
import * as Uint from 'tevm/Uint'

function calculatePercentage(
  amount: Wei.Type,
  percentage: bigint  // Basis points (100 = 1%)
): Wei.Type {
  const amountU256 = Wei.toU256(amount)
  const percentageU256 = Uint(percentage)
  const basis = Uint(10_000n)  // 100% = 10,000 basis points

  const result = Uint.dividedBy(
    Uint.times(amountU256, percentageU256),
    basis
  )

  return Wei(result)
}

// Example usage
const amount = Wei(1_000_000_000_000_000_000n)  // 1 ETH
const fee = calculatePercentage(amount, 250n)         // 2.5% fee
const remaining = Wei(
  Uint.minus(Wei.toU256(amount), Wei.toU256(fee))
)

console.log(`Original: ${amount} Wei`)
console.log(`Fee (2.5%): ${fee} Wei`)
console.log(`Remaining: ${remaining} Wei`)

Splitting Values

import * as Wei from 'tevm/Wei'
import * as Uint from 'tevm/Uint'

function splitEqually(
  total: Wei.Type,
  parts: number
): Wei.Type[] {
  const totalU256 = Wei.toU256(total)
  const partsU256 = Uint(BigInt(parts))

  const share = Uint.dividedBy(totalU256, partsU256)
  const remainder = Uint.modulo(totalU256, partsU256)

  // Create array of equal shares
  const shares = Array(parts).fill(Wei(share))

  // Add remainder to first share
  if (remainder > 0n) {
    shares[0] = Wei(Uint.plus(share, remainder))
  }

  return shares
}

// Example usage
const total = Wei(1_000_000_000_000_000_000n)  // 1 ETH
const shares = splitEqually(total, 3)

shares.forEach((share, i) => {
  console.log(`Share ${i + 1}: ${share} Wei`)
})

Price Calculations

ETH/USD Conversion

import * as Ether from 'tevm/Ether'
import * as Wei from 'tevm/Wei'
import * as Uint from 'tevm/Uint'

function weiToUSD(
  wei: Wei.Type,
  ethPriceUsd: number  // ETH price in USD (e.g., 2000.50)
): number {
  const weiU256 = Wei.toU256(wei)
  const weiPerEther = Uint(1_000_000_000_000_000_000n)

  // Convert to Ether (as number for USD calculation)
  const ether = Number(Uint.dividedBy(weiU256, weiPerEther))
  const fractionalWei = Number(Uint.modulo(weiU256, weiPerEther))
  const fractionalEther = fractionalWei / Number(weiPerEther)

  const totalEther = ether + fractionalEther
  return totalEther * ethPriceUsd
}

// Example usage
const balance = Wei(1_500_000_000_000_000_000n)  // 1.5 ETH
const ethPrice = 2000.50  // $2000.50 per ETH

const usdValue = weiToUSD(balance, ethPrice)
console.log(`Balance: $${usdValue.toFixed(2)} USD`)  // "$3000.75 USD"

Gas Cost in USD

import * as Gwei from 'tevm/Gwei'
import * as Wei from 'tevm/Wei'
import * as Uint from 'tevm/Uint'

function gasCostUSD(
  gasPriceGwei: Gwei.Type,
  gasUsed: bigint,
  ethPriceUsd: number
): number {
  // Calculate gas cost in Wei
  const gasPriceWei = Gwei.toWei(gasPriceGwei)
  const costWei = Uint.times(gasPriceWei, Uint(gasUsed))

  // Convert to USD
  const weiPerEther = Uint(1_000_000_000_000_000_000n)
  const costEther = Number(costWei) / Number(weiPerEther)

  return costEther * ethPriceUsd
}

// Example usage
const gasPrice = Gwei(50n)  // 50 Gwei
const gasUsed = 21_000n
const ethPrice = 2000.50

const costUsd = gasCostUSD(gasPrice, gasUsed, ethPrice)
console.log(`Gas cost: $${costUsd.toFixed(2)} USD`)

Validation

Range Checking

import * as Wei from 'tevm/Wei'
import * as Ether from 'tevm/Ether'
import * as Uint from 'tevm/Uint'

function isWithinRange(
  value: Wei.Type,
  min: Ether.Type,
  max: Ether.Type
): boolean {
  const valueU256 = Wei.toU256(value)
  const minWei = Ether.toWei(min)
  const maxWei = Ether.toWei(max)

  return valueU`256 >= Wei`.toU256(minWei) &&
         valueU`256 <= Wei`.toU256(maxWei)
}

// Example usage
const value = Wei(500_000_000_000_000_000n)  // 0.5 ETH
const min = Ether(0n)
const max = Ether(1n)

if (isWithinRange(value, min, max)) {
  console.log('Value within range')
}

Dust Amount Detection

import * as Wei from 'tevm/Wei'

const DUST_THRESHOLD = Wei(1_000_000_000_000n)  // 0.000001 ETH

function isDust(amount: Wei.Type): boolean {
  const amountU256 = Wei.toU256(amount)
  const thresholdU256 = Wei.toU256(DUST_THRESHOLD)
  return amountU256 < thresholdU256 && amountU256 > 0n
}

// Example usage
const amount = Wei(100n)
if (isDust(amount)) {
  console.log('Amount is dust - may not be worth sending')
}

Best Practices

  1. Store in Wei - Keep all values in Wei internally
  2. Convert at boundaries - Convert to Gwei/Ether only for display
  3. Use type safety - Let branded types prevent unit mixing
  4. Handle precision - Be aware of integer division truncation
  5. Validate inputs - Check ranges before conversions