Skip to main content

Try it Live

Run Authorization examples in the interactive playground

Constructors

Type guards and construction helpers for Authorization.

Type Guards

isItem

Check if value is signed Authorization.Item.
Authorization.isItem(value: unknown): value is Authorization.Item
Returns: true if value has all Authorization.Item fields Example:
import { Authorization } from 'tevm';

const data: unknown = getAuthFromAPI();

if (Authorization.isItem(data)) {
  // TypeScript knows data is Authorization.Item
  Authorization.validate.call(data);
  console.log(`Chain: ${data.chainId}`);
  console.log(`Nonce: ${data.nonce}`);
}
Type Guard Details: Checks for presence of all required fields:
  • chainId (bigint)
  • address (Address)
  • nonce (bigint)
  • yParity (number)
  • r (bigint)
  • s (bigint)
Implementation:
export function isItem(value: unknown): value is BrandedAuthorization {
  if (typeof value !== "object" || value === null) return false;
  const v = value as any;
  return (
    typeof v.chainId === "bigint" &&
    typeof v.address === "object" &&
    typeof v.nonce === "bigint" &&
    typeof v.yParity === "number" &&
    typeof v.r === "bigint" &&
    typeof v.s === "bigint"
  );
}

isUnsigned

Check if value is Authorization.Unsigned.
Authorization.isUnsigned(value: unknown): value is Authorization.Unsigned
Returns: true if value has all Authorization.Unsigned fields Example:
import { Authorization } from 'tevm';

const data: unknown = getUserAuth();

if (Authorization.isUnsigned(data)) {
  // TypeScript knows data is Authorization.Unsigned
  const hash = Authorization.hash.call(data);
  console.log(`Hash to sign: ${hash}`);
}
Type Guard Details: Checks for presence of unsigned fields:
  • chainId (bigint)
  • address (Address)
  • nonce (bigint)
Implementation:
export function isUnsigned(value: unknown): value is Unsigned {
  if (typeof value !== "object" || value === null) return false;
  const v = value as any;
  return (
    typeof v.chainId === "bigint" &&
    typeof v.address === "object" &&
    typeof v.nonce === "bigint"
  );
}

Creating Unsigned Authorizations

Manual Construction

import { Authorization, Address } from 'tevm';

const unsigned: Authorization.Unsigned = {
  chainId: 1n,
  address: Address('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2'),
  nonce: 0n
};

// Verify it's valid
if (Authorization.isUnsigned(unsigned)) {
  console.log('Valid unsigned authorization');
}

From Account State

import { Authorization, Address } from 'tevm';

async function createUnsignedAuth(
  eoa: Address,
  delegateTo: Address,
  chainId: bigint
): Promise<Authorization.Unsigned> {
  // Get current nonce from chain
  const nonce = await getAccountNonce(eoa);

  return {
    chainId,
    address: delegateTo,
    nonce
  };
}

const unsigned = await createUnsignedAuth(
  myEOA,
  contractAddress,
  1n
);

Batch Creation

import { Authorization, Address } from 'tevm';

function createAuthBatch(
  delegations: Array<{ to: Address; nonce: bigint }>,
  chainId: bigint
): Authorization.Unsigned[] {
  return delegations.map(d => ({
    chainId,
    address: d.to,
    nonce: d.nonce
  }));
}

const batch = createAuthBatch([
  { to: contract1, nonce: 0n },
  { to: contract2, nonce: 1n },
  { to: contract3, nonce: 2n }
], 1n);

// Verify all are unsigned
const allValid = batch.every(Authorization.isUnsigned);

Creating Signed Authorizations

See Signing for details on signing unsigned authorizations.
import { Authorization } from 'tevm';

// Create unsigned
const unsigned: Authorization.Unsigned = {
  chainId: 1n,
  address: contractAddress,
  nonce: 0n
};

// Sign it
const privateKey = Bytes32(); // Your private key
const auth = Authorization.sign.call(unsigned, privateKey);

// Verify it's signed
if (Authorization.isItem(auth)) {
  console.log('Valid signed authorization');
  console.log(`Signature: r=${auth.r}, s=${auth.s}, v=${auth.yParity}`);
}

Type Safety Patterns

Safe Type Narrowing

import { Authorization } from 'tevm';

function processAuth(data: unknown): void {
  if (!Authorization.isItem(data)) {
    throw new Error('Not a valid authorization');
  }

  // TypeScript knows data is Authorization.Item here
  Authorization.validate.call(data);
  const authority = Authorization.verify.call(data);
  console.log(`Signed by: ${authority}`);
}

Union Type Handling

import { Authorization } from 'tevm';

type AuthData = Authorization.Item | Authorization.Unsigned;

function formatAuth(auth: AuthData): string {
  if (Authorization.isItem(auth)) {
    // Signed authorization
    return Authorization.format.call(auth);
  } else if (Authorization.isUnsigned(auth)) {
    // Unsigned authorization
    return `Unsigned(chain=${auth.chainId}, to=${auth.address}, nonce=${auth.nonce})`;
  }
  throw new Error('Invalid authorization type');
}

Validation Pipeline

import { Authorization } from 'tevm';

interface ValidatedAuth {
  auth: Authorization.Item;
  authority: Address;
}

function validateAndProcess(data: unknown): ValidatedAuth {
  // Step 1: Type check
  if (!Authorization.isItem(data)) {
    throw new Error('Invalid authorization type');
  }

  // Step 2: Structure validation
  Authorization.validate.call(data);

  // Step 3: Signature verification
  const authority = Authorization.verify.call(data);

  return { auth: data, authority };
}

Common Patterns

API Response Handler

import { Authorization } from 'tevm';

interface ApiResponse {
  authorizations: unknown[];
}

function parseAuthResponse(response: ApiResponse): Authorization.Item[] {
  const validAuths: Authorization.Item[] = [];

  for (const auth of response.authorizations) {
    if (Authorization.isItem(auth)) {
      try {
        Authorization.validate.call(auth);
        validAuths.push(auth);
      } catch (e) {
        console.error(`Invalid auth: ${e}`);
      }
    } else {
      console.error('Not an authorization item');
    }
  }

  return validAuths;
}

Factory Pattern

import { Authorization, Address } from 'tevm';

class AuthorizationFactory {
  constructor(
    private chainId: bigint,
    private privateKey: Uint8Array
  ) {}

  createUnsigned(
    delegateTo: Address,
    nonce: bigint
  ): Authorization.Unsigned {
    const unsigned = {
      chainId: this.chainId,
      address: delegateTo,
      nonce
    };

    // Verify type
    if (!Authorization.isUnsigned(unsigned)) {
      throw new Error('Failed to create unsigned authorization');
    }

    return unsigned;
  }

  createSigned(
    delegateTo: Address,
    nonce: bigint
  ): Authorization.Item {
    const unsigned = this.createUnsigned(delegateTo, nonce);
    const auth = Authorization.sign.call(unsigned, this.privateKey);

    // Verify type
    if (!Authorization.isItem(auth)) {
      throw new Error('Failed to create signed authorization');
    }

    return auth;
  }
}

const factory = new AuthorizationFactory(1n, privateKey);
const auth = factory.createSigned(contractAddress, 0n);

Builder Pattern

import { Authorization, Address } from 'tevm';

class AuthorizationBuilder {
  private chainId?: bigint;
  private address?: Address;
  private nonce?: bigint;

  setChainId(chainId: bigint): this {
    this.chainId = chainId;
    return this;
  }

  setAddress(address: Address): this {
    this.address = address;
    return this;
  }

  setNonce(nonce: bigint): this {
    this.nonce = nonce;
    return this;
  }

  buildUnsigned(): Authorization.Unsigned {
    if (this.chainId === undefined) throw new Error('chainId required');
    if (this.address === undefined) throw new Error('address required');
    if (this.nonce === undefined) throw new Error('nonce required');

    const unsigned = {
      chainId: this.chainId,
      address: this.address,
      nonce: this.nonce
    };

    if (!Authorization.isUnsigned(unsigned)) {
      throw new Error('Invalid unsigned authorization');
    }

    return unsigned;
  }

  buildSigned(privateKey: Uint8Array): Authorization.Item {
    const unsigned = this.buildUnsigned();
    return Authorization.sign.call(unsigned, privateKey);
  }
}

const auth = new AuthorizationBuilder()
  .setChainId(1n)
  .setAddress(contractAddress)
  .setNonce(0n)
  .buildSigned(privateKey);

Validation Helpers

Safe Constructor

import { Authorization, Address } from 'tevm';

function safeCreateUnsigned(
  chainId: unknown,
  address: unknown,
  nonce: unknown
): Authorization.Unsigned {
  // Validate types
  if (typeof chainId !== 'bigint') {
    throw new Error('chainId must be bigint');
  }
  if (!Address.is(address)) {
    throw new Error('address must be Address');
  }
  if (typeof nonce !== 'bigint') {
    throw new Error('nonce must be bigint');
  }

  const unsigned = { chainId, address, nonce };

  // Final type check
  if (!Authorization.isUnsigned(unsigned)) {
    throw new Error('Failed to create unsigned authorization');
  }

  return unsigned;
}

Array Validator

import { Authorization } from 'tevm';

function validateAuthArray(data: unknown[]): Authorization.Item[] {
  const valid: Authorization.Item[] = [];
  const errors: string[] = [];

  for (let i = 0; i < data.length; i++) {
    const item = data[i];

    if (!Authorization.isItem(item)) {
      errors.push(`Index ${i}: not an authorization item`);
      continue;
    }

    try {
      Authorization.validate.call(item);
      valid.push(item);
    } catch (e) {
      errors.push(`Index ${i}: ${e}`);
    }
  }

  if (errors.length > 0 && valid.length === 0) {
    throw new Error(`All authorizations invalid: ${errors.join(', ')}`);
  }

  return valid;
}

See Also