Skip to main content

Overview

BundleHash is a branded Uint8Array type representing a 32-byte identifier for MEV transaction bundles. Computed as keccak256 of concatenated transaction hashes, it’s used to track bundle status through MEV relays and block builders like Flashbots.
import * as BundleHash from '@tevm/primitives/BundleHash'

const hash = BundleHash.fromHex(
  '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
)

Type Definition

type BundleHashType = Uint8Array & {
  readonly [brand]: "BundleHash";
  readonly length: 32;
}

type BundleHashLike = BundleHashType | string | Uint8Array

Constants

const SIZE = 32  // Bundle hash is always 32 bytes

Creating BundleHashes

from

Universal constructor accepting hex string or bytes.
// From hex string (with 0x prefix)
const hash1 = BundleHash.from(
  '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
)

// From hex string (without prefix)
const hash2 = BundleHash.from(
  '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
)

// From Uint8Array
const bytes = new Uint8Array(32)
const hash3 = BundleHash.from(bytes)
Throws InvalidBundleHashError if:
  • Bytes length is not 32
  • Hex string is not 64 characters
  • Invalid hex characters
  • Unsupported input type

fromHex

Parse from hex string (with or without 0x prefix).
const hash = BundleHash.fromHex(
  '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
)
Validation: Must be exactly 64 hex characters (32 bytes).

fromBundle

Compute bundle hash from a Bundle containing transactions. Requires a keccak256 implementation.
import * as BundleHash from '@tevm/primitives/BundleHash'
import { keccak256 } from '@tevm/crypto/keccak256'

const bundle = {
  transactions: [tx1, tx2, tx3]
}

const hash = BundleHash.fromBundle(bundle, { keccak256 })
The hash is computed by:
  1. Hashing each transaction with keccak256
  2. Concatenating all transaction hashes
  3. Hashing the concatenated result
This matches the bundle hash format used by Flashbots and other MEV relays.

Converting BundleHashes

toHex

Convert to lowercase hex string with 0x prefix.
const hex = BundleHash.toHex(hash)
// '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'

Comparing BundleHashes

equals

Check equality using byte comparison.
const a = BundleHash.fromHex('0x1234...')
const b = BundleHash.fromHex('0x1234...')

if (BundleHash.equals(a, b)) {
  console.log('Bundle hashes match')
}

Errors

BundleHash provides typed errors that extend the Voltaire error hierarchy:

InvalidBundleHashError

Thrown when BundleHash operations fail due to invalid data.
import { InvalidBundleHashError } from '@tevm/primitives/BundleHash'

try {
  BundleHash.from(new Uint8Array(16)) // Wrong length
} catch (e) {
  if (e instanceof InvalidBundleHashError) {
    console.log(e.name)     // "InvalidBundleHashError"
    console.log(e.code)     // "INVALID_BUNDLE_HASH"
    console.log(e.value)    // The invalid value
    console.log(e.expected) // "32-byte bundle hash"
  }
}

MissingCryptoDependencyError

Thrown when required crypto function is not provided.
import { MissingCryptoDependencyError } from '@tevm/primitives/BundleHash'

try {
  BundleHash.fromBundle(bundle, {}) // Missing keccak256
} catch (e) {
  if (e instanceof MissingCryptoDependencyError) {
    console.log(e.name)     // "MissingCryptoDependencyError"
    console.log(e.code)     // "MISSING_CRYPTO_DEPENDENCY"
    console.log(e.expected) // "{ keccak256: (data: Uint8Array) => Uint8Array }"
  }
}

Error Types

ErrorExtendsCodeWhen Thrown
InvalidBundleHashErrorInvalidLengthErrorINVALID_BUNDLE_HASHInvalid hash format or length
MissingCryptoDependencyErrorValidationErrorMISSING_CRYPTO_DEPENDENCYkeccak256 not provided
Common scenarios:
  • Invalid byte length (not 32 bytes)
  • Invalid hex string length (not 64 characters)
  • Invalid hex characters
  • Unsupported input type
  • Missing keccak256 dependency in fromBundle

MEV Use Cases

Tracking Bundle Status

import * as BundleHash from '@tevm/primitives/BundleHash'

// After submitting bundle to Flashbots
const bundleHash = BundleHash.from(response.bundleHash)
const hex = BundleHash.toHex(bundleHash)

// Query bundle status
const status = await relay.getBundleStats(hex)

Verifying Bundle Inclusion

// Compute expected hash locally
const expectedHash = BundleHash.fromBundle(bundle, { keccak256 })

// Compare with relay response
if (BundleHash.equals(expectedHash, receivedHash)) {
  console.log('Bundle hash verified')
}

See Also