Skip to main content

Try it Live

Run Address examples in the interactive playground
This page is a placeholder. All examples on this page are currently AI-generated and are not correct. This documentation will be completed in the future with accurate, tested examples.
View the complete executable example at playground/src/examples/primitives/address/compare.ts.

C API - Manual Implementation Required

The C API currently provides primitives_address_equals() but not a three-way comparison. Implement lexicographic comparison manually:Example:
#include "tevm.h"
#include <string.h>

// Custom compare function for addresses
int address_compare(const PrimitivesAddress* a, const PrimitivesAddress* b) {
    // Compare bytes lexicographically
    for (int i = 0; i < 20; i++) {
        if (a->bytes[i] < b->bytes[i]) return -1;
        if (a->bytes[i] > b->bytes[i]) return 1;
    }
    return 0;
}

// Usage
PrimitivesAddress addr1;
PrimitivesAddress addr2;
PrimitivesAddress addr3;

primitives_address_from_hex("0x000000000000000000000000000000000000000a", &addr1);
primitives_address_from_hex("0x0000000000000000000000000000000000000014", &addr2);
primitives_address_from_hex("0x000000000000000000000000000000000000000a", &addr3);

int cmp1 = address_compare(&addr1, &addr2);
int cmp2 = address_compare(&addr2, &addr1);
int cmp3 = address_compare(&addr1, &addr3);

printf("%d\n", cmp1);  // -1 (addr1 < addr2)
printf("%d\n", cmp2);  // 1  (addr2 > addr1)
printf("%d\n", cmp3);  // 0  (addr1 == addr3)

// Use with qsort for sorting
int compare_wrapper(const void* a, const void* b) {
    return address_compare((const PrimitivesAddress*)a, (const PrimitivesAddress*)b);
}

PrimitivesAddress addresses[] = {addr2, addr1, addr3};
qsort(addresses, 3, sizeof(PrimitivesAddress), compare_wrapper);
Alternative: Use memcmp for byte-level comparison:
int cmp = memcmp(addr1.bytes, addr2.bytes, 20);
// Returns: <0 if addr1 < addr2, 0 if equal, >0 if addr1 > addr2
See also: primitives_address_equals() for equality comparison

Comparison Semantics

Lexicographic ordering: Compares byte-by-byte from left to right (big-endian). Return values:
  • -1: First address is less than second
  • 0: Addresses are equal
  • 1: First address is greater than second
Example ordering:
import { Address } from '@tevm/voltaire'

const a1 = Address("0x0000000000000000000000000000000000000001")
const a2 = Address("0x0000000000000000000000000000000000000002")
const a3 = Address("0x1000000000000000000000000000000000000000")

// Lexicographic order: a1 < a2 < a3
console.log(a1.compare(a2)) // -1
console.log(a2.compare(a3)) // -1
console.log(a1.compare(a3)) // -1
console.log(a3.compare(a1)) // 1

Use Cases

Sorting Arrays

Sort addresses in ascending or descending order:
import { Address } from '@tevm/voltaire'

const addresses = [
  Address("0xffffffffffffffffffffffffffffffffffffffff"),
  Address("0x0000000000000000000000000000000000000001"),
  Address("0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e"),
]

// Sort ascending
addresses.sort((a, b) => a.compare(b))

// Sort descending
addresses.sort((a, b) => b.compare(a))
Efficient lookup in sorted arrays:
import { Address } from '@tevm/voltaire'

function binarySearch(sorted: Address[], target: Address): number {
  let left = 0
  let right = sorted.length - 1

  while (left <= right) {
    const mid = Math.floor((left + right) / 2)
    const cmp = sorted[mid].compare(target)

    if (cmp === 0) return mid
    if (cmp < 0) left = mid + 1
    else right = mid - 1
  }

  return -1 // Not found
}

Ordered Sets

Maintain addresses in sorted order:
import { Address } from '@tevm/voltaire'

class AddressSet {
  private addresses: Address[] = []

  add(address: Address) {
    // Find insertion point
    const index = this.addresses.findIndex(a => a.compare(address) >= 0)

    if (index === -1) {
      this.addresses.push(address)
    } else if (this.addresses[index].compare(address) !== 0) {
      this.addresses.splice(index, 0, address)
    }
  }

  has(address: Address): boolean {
    const index = binarySearch(this.addresses, address)
    return index !== -1
  }
}

Range Queries

Find addresses within a range:
import { Address } from '@tevm/voltaire'

function getAddressesInRange(
  addresses: Address[],
  min: Address,
  max: Address
): Address[] {
  return addresses.filter(addr =>
    addr.compare(min) >= 0 && addr.compare(max) <= 0
  )
}

Merkle Trees

Build ordered merkle trees using address ordering:
import { Address } from '@tevm/voltaire'

function buildMerkleTree(addresses: Address[]) {
  // Sort addresses first
  const sorted = [...addresses].sort((a, b) => a.compare(b))

  // Build tree with sorted addresses
  // ...
}

Performance

Time complexity: O(n) where n = 20 bytes (constant time for addresses) Implementation: Compares byte-by-byte until difference found or end reached Early termination: Stops at first differing byte For large-scale sorting, consider converting to hex once:
import { Address } from '@tevm/voltaire'

// Less efficient (converts to hex repeatedly)
addresses.sort((a, b) => a.compare(b))

// More efficient (convert once)
const withHex = addresses.map(addr => ({ addr, hex: addr.toHex() }))
withHex.sort((a, b) => a.hex.localeCompare(b.hex))
const sorted = withHex.map(({ addr }) => addr)

Relation to Other Comparisons

import { Address } from '@tevm/voltaire'

const addr1 = Address(10n)
const addr2 = Address(20n)

// compare() returns -1, 0, or 1
const result = addr1.compare(addr2)

// Equivalent to:
if (addr1.lessThan(addr2)) {
  // result === -1
} else if (addr1.equals(addr2)) {
  // result === 0
} else if (addr1.greaterThan(addr2)) {
  // result === 1
}
Helper methods built on compare():
addr1.lessThan(addr2)    === (addr1.compare(addr2) < 0)
addr1.greaterThan(addr2) === (addr1.compare(addr2) > 0)
addr1.equals(addr2)      === (addr1.compare(addr2) === 0)

Sorting Examples

Sort transaction list by sender:

import { Address } from '@tevm/voltaire'

interface Transaction {
  from: Address
  to: Address
  value: bigint
}

function sortBySender(txs: Transaction[]): Transaction[] {
  return txs.sort((a, b) => a.from.compare(b.from))
}

Group addresses by range:

import { Address } from '@tevm/voltaire'

function groupByRange(addresses: Address[], rangeSize: bigint) {
  const sorted = [...addresses].sort((a, b) => a.compare(b))
  const groups: Address[][] = []
  let currentGroup: Address[] = []

  for (const addr of sorted) {
    if (currentGroup.length === 0) {
      currentGroup.push(addr)
    } else {
      const first = currentGroup[0]
      const diff = addr.toU256() - first.toU256()

      if (diff < rangeSize) {
        currentGroup.push(addr)
      } else {
        groups.push(currentGroup)
        currentGroup = [addr]
      }
    }
  }

  if (currentGroup.length > 0) {
    groups.push(currentGroup)
  }

  return groups
}

See Also