CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-web3-eth-abi

Web3 module encode and decode EVM in/output.

Pending
Overview
Eval results
Files

eip-712.mddocs/

EIP-712 Structured Data

Complete support for EIP-712 structured data encoding and message preparation for typed data signing. Essential for implementing secure off-chain message signing with structured data.

Capabilities

Get Encoded EIP-712 Data

Gets the EIP-191 encoded message to sign from typed data object. Implements the EIP-712 standard for structured data hashing and signing.

/**
 * Gets EIP-191 encoded message from typed data for signing
 * @param typedData - The EIP-712 typed data object
 * @param hash - Whether to hash the message with Keccak256
 * @returns The encoded message (hashed if hash=true)
 */
function getEncodedEip712Data(
  typedData: Eip712TypedData,
  hash?: boolean
): string;

Usage Examples:

import { getEncodedEip712Data } from "web3-eth-abi";

// Define EIP-712 typed data
const typedData = {
  types: {
    EIP712Domain: [
      { name: "name", type: "string" },
      { name: "version", type: "string" },
      { name: "chainId", type: "uint256" },
      { name: "verifyingContract", type: "address" }
    ],
    Person: [
      { name: "name", type: "string" },
      { name: "wallet", type: "address" }
    ],
    Mail: [
      { name: "from", type: "Person" },
      { name: "to", type: "Person" },
      { name: "contents", type: "string" }
    ]
  },
  primaryType: "Mail",
  domain: {
    name: "Ether Mail",
    version: "1",
    chainId: 1,
    verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
  },
  message: {
    from: {
      name: "Cow",
      wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"
    },
    to: {
      name: "Bob",
      wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
    },
    contents: "Hello, Bob!"
  }
};

// Get encoded message for signing (not hashed)
const encodedMessage = getEncodedEip712Data(typedData, false);
console.log(encodedMessage);
// 0x1901... (EIP-191 prefix + domain separator + message hash)

// Get hashed message for signing
const hashedMessage = getEncodedEip712Data(typedData, true);  
console.log(hashedMessage);
// 0x... (Keccak256 hash of the encoded message)

// Use with eth_signTypedData_v4
// The hashed message can be used directly with wallet signing methods

EIP-712 Structure

Domain Separator

The domain separator ensures that signatures are specific to a particular application and chain:

interface EIP712Domain {
  name?: string;          // Human readable name of signing domain
  version?: string;       // Current major version of signing domain
  chainId?: number;       // EIP-155 chain id
  verifyingContract?: string; // Address of contract that will verify signature
  salt?: string;          // Disambiguating salt for protocol
}

Typed Data Structure

interface Eip712TypedData {
  types: Record<string, Array<{ name: string; type: string }>>;
  primaryType: string;
  domain: Record<string, unknown>;
  message: Record<string, unknown>;
}

Type Definitions

Custom types are defined in the types object, with each type specifying its fields and their types:

const types = {
  Person: [
    { name: "name", type: "string" },
    { name: "wallet", type: "address" }
  ],
  Mail: [
    { name: "from", type: "Person" },     // References Person type
    { name: "to", type: "Person" },
    { name: "contents", type: "string" }
  ]
};

Advanced Usage Examples

Token Permit (ERC-2612)

const permitTypedData = {
  types: {
    EIP712Domain: [
      { name: "name", type: "string" },
      { name: "version", type: "string" },
      { name: "chainId", type: "uint256" },
      { name: "verifyingContract", type: "address" }
    ],
    Permit: [
      { name: "owner", type: "address" },
      { name: "spender", type: "address" },
      { name: "value", type: "uint256" },
      { name: "nonce", type: "uint256" },
      { name: "deadline", type: "uint256" }
    ]
  },
  primaryType: "Permit",
  domain: {
    name: "MyToken",
    version: "1",
    chainId: 1,
    verifyingContract: "0x1234567890123456789012345678901234567890"
  },
  message: {
    owner: "0xowner...",
    spender: "0xspender...",
    value: "1000000000000000000", // 1 token
    nonce: 0,
    deadline: 1700000000
  }
};

const permitHash = getEncodedEip712Data(permitTypedData, true);

Order Signing (DEX/Marketplace)

const orderTypedData = {
  types: {
    EIP712Domain: [
      { name: "name", type: "string" },
      { name: "version", type: "string" },
      { name: "chainId", type: "uint256" },
      { name: "verifyingContract", type: "address" }
    ],
    Order: [
      { name: "maker", type: "address" },
      { name: "taker", type: "address" },
      { name: "tokenA", type: "address" },
      { name: "tokenB", type: "address" },
      { name: "amountA", type: "uint256" },
      { name: "amountB", type: "uint256" },
      { name: "expiry", type: "uint256" },
      { name: "nonce", type: "uint256" }
    ]
  },
  primaryType: "Order",
  domain: {
    name: "MyDEX",
    version: "1",
    chainId: 1,
    verifyingContract: "0xDEX_CONTRACT_ADDRESS"
  },
  message: {
    maker: "0xmaker...",
    taker: "0x0000000000000000000000000000000000000000", // Any taker
    tokenA: "0xTokenA...",
    tokenB: "0xTokenB...",
    amountA: "1000000000000000000",
    amountB: "500000000000000000",
    expiry: 1700000000,
    nonce: 1
  }
};

const orderHash = getEncodedEip712Data(orderTypedData, true);

Implementation Details

Encoding Process

  1. Type Hash: Calculate keccak256 of the encoded type definition
  2. Struct Hash: Calculate keccak256 of type hash + encoded values
  3. Domain Separator: Calculate keccak256 of domain type hash + domain values
  4. Final Message: EIP-191 prefix + domain separator + message hash

Array Handling

Arrays in EIP-712 are encoded by hashing each element recursively and then hashing the concatenated hashes.

String and Bytes Handling

Strings and dynamic bytes are hashed using keccak256 when used in structured data.

Types

interface Eip712TypedData {
  types: Record<string, Array<{ name: string; type: string }>>;
  primaryType: string;
  domain: Record<string, unknown>;
  message: Record<string, unknown>;
}

interface EIP712Domain {
  name?: string;
  version?: string; 
  chainId?: number;
  verifyingContract?: string;
  salt?: string;
}

Install with Tessl CLI

npx tessl i tessl/npm-web3-eth-abi

docs

eip-712.md

error-handling.md

event-processing.md

function-operations.md

index.md

parameter-processing.md

tile.json