Skip to main content
Checks whether a value can be safely converted to CallData without throwing an error. Useful for input validation.

Signature

function isValid(value: unknown): boolean

Parameters

  • value - Value to validate (any type)

Returns

boolean - true if value can be converted to CallData, false otherwise

Examples

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

// Valid hex strings
console.log(CallData.isValid("0xa9059cbb")); // true
console.log(CallData.isValid("a9059cbb")); // true

// Valid byte arrays
const bytes = new Uint8Array([0xa9, 0x05, 0x9c, 0xbb]);
console.log(CallData.isValid(bytes)); // true

// Invalid inputs
console.log(CallData.isValid("0xGGGG")); // false (invalid hex)
console.log(CallData.isValid("0x1234")); // false (too short)
console.log(CallData.isValid(null)); // false
console.log(CallData.isValid(undefined)); // false
console.log(CallData.isValid(123)); // false

Validation Rules

Checks multiple criteria:
import { CallData } from '@tevm/voltaire';

// Must be valid hex
CallData.isValid("0xGGGG"); // false (invalid chars)
CallData.isValid("0xa9059cbb"); // true

// Must be byte-aligned (even length)
CallData.isValid("0xa905"); // true (2 bytes)
CallData.isValid("0xa90"); // false (odd length)

// Must have at least 4 bytes (selector)
CallData.isValid("0xa9"); // false (1 byte)
CallData.isValid("0xa9059cbb"); // true (4 bytes)

Use Cases

API Input Validation

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

interface SendTransactionParams {
  to: string;
  data: string;
  value?: string;
}

function validateTransactionParams(
  params: SendTransactionParams
): string[] {
  const errors: string[] = [];

  if (!CallData.isValid(params.data)) {
    errors.push("Invalid calldata format");
  }

  if (!Address.isValid(params.to)) {
    errors.push("Invalid recipient address");
  }

  return errors;
}

Safe Constructor Pattern

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

function safeCallData(value: unknown): CallDataType | null {
  if (!CallData.isValid(value)) {
    console.warn("Invalid calldata:", value);
    return null;
  }

  return CallData(value);
}

// Usage
const calldata = safeCallData(userInput);
if (calldata) {
  processCallData(calldata);
}

Form Validation

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

function validateCalldataInput(input: string): {
  valid: boolean;
  error?: string;
} {
  if (!input) {
    return { valid: false, error: "Calldata required" };
  }

  if (!CallData.isValid(input)) {
    return { valid: false, error: "Invalid calldata format" };
  }

  const calldata = CallData(input);
  if (calldata.length < 4) {
    return { valid: false, error: "Must include function selector" };
  }

  return { valid: true };
}

Batch Validation

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

interface TransactionInput {
  id: string;
  data: string;
}

function validateBatch(
  txs: TransactionInput[]
): { valid: TransactionInput[]; invalid: TransactionInput[] } {
  const valid: TransactionInput[] = [];
  const invalid: TransactionInput[] = [];

  for (const tx of txs) {
    if (CallData.isValid(tx.data)) {
      valid.push(tx);
    } else {
      invalid.push(tx);
    }
  }

  return { valid, invalid };
}

Performance

Validation is fast (basic checks only):
// Benchmark: 1M iterations
const validHex = "0xa9059cbb...";
const invalidHex = "0xGGGG";

console.time("isValid (valid)");
for (let i = 0; i < 1_000_000; i++) {
  CallData.isValid(validHex);
}
console.timeEnd("isValid (valid)");
// ~40ms

console.time("isValid (invalid)");
for (let i = 0; i < 1_000_000; i++) {
  CallData.isValid(invalidHex);
}
console.timeEnd("isValid (invalid)");
// ~15ms (fails fast)
Validation fails early on invalid input.

Comparison with Constructor

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

// No exceptions
if (CallData.isValid(input)) {
  const calldata = CallData(input);
  // Safe to use
}
Advantages:
  • No try-catch needed
  • Clear validation logic
  • Better performance (checks once)
Use isValid for cleaner validation logic.

Type Narrowing

TypeScript doesn’t narrow types with isValid:
import { CallData, type CallDataType } from '@tevm/voltaire';

function process(input: unknown) {
  if (CallData.isValid(input)) {
    // input is still 'unknown' (not narrowed to string | Uint8Array)
    const calldata = CallData(input); // Must still construct
  }
}
For type narrowing, use is() type guard instead.

Validation Errors

Does not provide detailed error messages:
// isValid just returns false
console.log(CallData.isValid("0xGGGG")); // false

// Constructor throws with details
try {
  CallData("0xGGGG");
} catch (error) {
  console.error(error.message); // "Invalid hex character: G"
}
For detailed errors, use constructor in try-catch.
  • is - Type guard with narrowing
  • from - Universal constructor
  • fromHex - Parse hex string
  • fromBytes - Create from bytes