Skip to main content
Returns the underlying Uint8Array representation of CallData. Zero-copy operation that provides access to raw bytes.

Signature

function toBytes(calldata: CallDataType): Uint8Array

Parameters

  • calldata - CallData instance to convert

Returns

Uint8Array - Raw byte array (shares underlying buffer)

Examples

import { CallData } from '@tevm/voltaire';

const calldata = CallData("0xa9059cbb...");
const bytes = CallData.toBytes(calldata);

console.log(bytes);
// Uint8Array(68) [169, 5, 156, 187, 0, 0, ...]

Zero-Copy Behavior

toBytes returns the same underlying buffer:
import { CallData } from '@tevm/voltaire';

const original = new Uint8Array([0xa9, 0x05, 0x9c, 0xbb]);
const calldata = CallData.fromBytes(original);
const bytes = CallData.toBytes(calldata);

// All share same buffer
console.log(original.buffer === calldata.buffer); // true
console.log(calldata.buffer === bytes.buffer); // true

// Mutations visible across all views
bytes[0] = 0xff;
console.log(original[0]); // 0xff
console.log(calldata[0]); // 0xff
Important: Mutating bytes affects the original CallData.

Use Cases

Binary Protocols

import { CallData } from '@tevm/voltaire';

// Send over WebSocket
async function sendBinary(ws: WebSocket, calldata: CallDataType) {
  const bytes = CallData.toBytes(calldata);
  ws.send(bytes); // Direct binary transmission
}

// Receive and parse
ws.onmessage = (event) => {
  const bytes = new Uint8Array(event.data);
  const calldata = CallData.fromBytes(bytes);
};

File Operations

import { CallData } from '@tevm/voltaire';
import { writeFileSync } from 'fs';

// Write calldata to file
function saveCallData(calldata: CallDataType, path: string) {
  const bytes = CallData.toBytes(calldata);
  writeFileSync(path, bytes);
}

// Read from file
function loadCallData(path: string): CallDataType {
  const buffer = readFileSync(path);
  return CallData.fromBytes(new Uint8Array(buffer));
}

Performance-Critical Operations

import { CallData } from '@tevm/voltaire';

// Extract selector without string conversion
function fastGetSelector(calldata: CallDataType): Uint8Array {
  const bytes = CallData.toBytes(calldata);
  return bytes.slice(0, 4); // Direct byte access
}

// Compare calldata
function fastEquals(a: CallDataType, b: CallDataType): boolean {
  const bytesA = CallData.toBytes(a);
  const bytesB = CallData.toBytes(b);

  if (bytesA.length !== bytesB.length) return false;

  for (let i = 0; i < bytesA.length; i++) {
    if (bytesA[i] !== bytesB[i]) return false;
  }

  return true;
}

WASM Interop

import { CallData } from '@tevm/voltaire';
import { wasmModule } from './crypto.wasm';

// Pass bytes to WASM
function hashCallData(calldata: CallDataType): Uint8Array {
  const bytes = CallData.toBytes(calldata);

  // WASM operates on byte arrays
  return wasmModule.keccak256(bytes);
}

Performance

toBytes is effectively zero-cost:
// Benchmark: 10M iterations
const calldata = CallData("0xa9059cbb...");

console.time("toBytes");
for (let i = 0; i < 10_000_000; i++) {
  CallData.toBytes(calldata);
}
console.timeEnd("toBytes");

// ~50ms (just pointer return, no copy)
Compare with toHex:
console.time("toHex");
for (let i = 0; i < 10_000_000; i++) {
  CallData.toHex(calldata);
}
console.timeEnd("toHex");

// ~1200ms (hex encoding overhead)
toBytes is ~24x faster than toHex for this workload.

Immutability Considerations

While CallData is conceptually immutable, toBytes exposes mutable buffer:
import { CallData } from '@tevm/voltaire';

// Create immutable copy
function toBytesCopy(calldata: CallDataType): Uint8Array {
  const bytes = CallData.toBytes(calldata);
  return new Uint8Array(bytes); // Copy
}

// Safe: Mutations don't affect original
const calldata = CallData("0xa9059cbb");
const copy = toBytesCopy(calldata);
copy[0] = 0xff;
console.log(calldata[0]); // 0xa9 (unchanged)
For public APIs, consider returning copies to maintain immutability guarantees.

Type Safety

Output is plain Uint8Array (no CallData brand):
import { CallData, type CallDataType } from '@tevm/voltaire';

const calldata: CallDataType = CallData("0xa9059cbb");
const bytes: Uint8Array = CallData.toBytes(calldata);

// Cannot use as CallData without constructor
const calldata2: CallDataType = bytes; // ❌ Type error
const calldata3: CallDataType = CallData.fromBytes(bytes); // ✅

Comparison with toHex

Advantages:
  • Zero-copy (24x faster)
  • Binary protocols (WebSocket, files)
  • WASM interop
  • Direct byte manipulation
Use for:
  • Performance-critical paths
  • Binary I/O
  • Cryptographic operations
  • Memory-efficient processing