CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-web3-eth

Web3 module to interact with the Ethereum blockchain and smart contracts.

67

0.98x
Overview
Eval results
Files

cryptographic-operations.mddocs/

Cryptographic Operations

The cryptographic operations functionality provides comprehensive signing capabilities including message signing, transaction signing, and EIP-712 typed data signing with support for various signature formats.

Message Signing

sign

Signs arbitrary messages using an account's private key.

sign(message: Bytes, addressOrIndex: Address | Numbers, returnFormat?: DataFormat): Promise<SignatureObject>;

Parameters:

  • message: The message to sign (hex string or bytes)
  • addressOrIndex: Account address or wallet index to sign with
  • returnFormat: Output format configuration

Usage Example:

// Sign a simple message
const message = "Hello, Ethereum!";
const signature = await eth.sign(message, "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E");

console.log("Message signature:", {
  messageHash: signature.messageHash,
  r: signature.r,
  s: signature.s,
  v: signature.v,
  signature: signature.signature
});

// Sign hex-encoded data
const hexMessage = "0x48656c6c6f2c20457468657265756d21"; // "Hello, Ethereum!" in hex
const hexSignature = await eth.sign(hexMessage, "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E");

// Verify signature (using web3-utils)
import { recover } from "web3-utils";
const recoveredAddress = recover(message, signature.signature);
console.log("Signature verification:", recoveredAddress === "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E");

Transaction Signing

signTransaction

Signs a transaction without broadcasting it to the network.

signTransaction(transaction: Transaction, returnFormat?: DataFormat): Promise<SignedTransactionInfoAPI>;

Usage Example:

// Sign a transaction for later broadcast
const transaction = {
  from: "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E",
  to: "0x8ba1f109551bD432803012645Hac136c1c1b6c5E",
  value: "1000000000000000000", // 1 ETH
  gas: "21000",
  gasPrice: "20000000000", // 20 Gwei
  nonce: await eth.getTransactionCount("0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E")
};

const signedTx = await eth.signTransaction(transaction);
console.log("Signed transaction:", {
  messageHash: signedTx.messageHash,
  r: signedTx.r,
  s: signedTx.s,
  v: signedTx.v,
  rawTransaction: signedTx.rawTransaction
});

// Broadcast the signed transaction later
const receipt = await eth.sendSignedTransaction(signedTx.rawTransaction);

EIP-1559 Transaction Signing

// Sign EIP-1559 transaction
const eip1559Transaction = {
  from: "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E",
  to: "0x8ba1f109551bD432803012645Hac136c1c1b6c5E",
  value: "1000000000000000000",
  gas: "21000",
  maxFeePerGas: "30000000000", // 30 Gwei
  maxPriorityFeePerGas: "2000000000", // 2 Gwei
  nonce: await eth.getTransactionCount("0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E"),
  type: 2 // EIP-1559
};

const signed1559Tx = await eth.signTransaction(eip1559Transaction);

EIP-712 Typed Data Signing

signTypedData

Signs structured data according to EIP-712 standard for improved user experience and security.

signTypedData(address: Address, typedData: Eip712TypedData, useLegacy?: boolean, returnFormat?: DataFormat): Promise<SignatureObject>;

Parameters:

  • address: Signer's address
  • typedData: EIP-712 structured data object
  • useLegacy: Use legacy signing format (default: false)
  • returnFormat: Output format configuration

Usage Example:

// Define EIP-712 domain and types
const domain = {
  name: "MyDApp",
  version: "1",
  chainId: 1,
  verifyingContract: "0x1234567890123456789012345678901234567890"
};

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

const message = {
  from: {
    name: "Alice",
    wallet: "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E"
  },
  to: {
    name: "Bob", 
    wallet: "0x8ba1f109551bD432803012645Hac136c1c1b6c5E"
  },
  contents: "Hello Bob!"
};

const typedData = {
  domain,
  types,
  primaryType: "Mail",
  message
};

// Sign the typed data
const signature = await eth.signTypedData(
  "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E",
  typedData
);

console.log("EIP-712 signature:", signature);

Common EIP-712 Use Cases

ERC-20 Permit Signing

// Sign ERC-20 permit for gasless approvals
async function signPermit(
  tokenAddress: Address,
  owner: Address,
  spender: Address,
  value: string,
  deadline: number,
  nonce: number
) {
  const domain = {
    name: "Token Name", // Get from token contract
    version: "1",
    chainId: await eth.getChainId(),
    verifyingContract: tokenAddress
  };

  const types = {
    Permit: [
      { name: "owner", type: "address" },
      { name: "spender", type: "address" },
      { name: "value", type: "uint256" },
      { name: "nonce", type: "uint256" },
      { name: "deadline", type: "uint256" }
    ]
  };

  const message = {
    owner,
    spender,
    value,
    nonce,
    deadline
  };

  const typedData = {
    domain,
    types,
    primaryType: "Permit",
    message
  };

  return await eth.signTypedData(owner, typedData);
}

MetaTransaction Signing

// Sign meta-transaction for gasless execution
async function signMetaTransaction(
  from: Address,
  to: Address,
  data: string,
  nonce: number,
  relayerAddress: Address
) {
  const domain = {
    name: "MetaTransactionRelay",
    version: "1",
    chainId: await eth.getChainId(),
    verifyingContract: relayerAddress
  };

  const types = {
    MetaTransaction: [
      { name: "from", type: "address" },
      { name: "to", type: "address" },
      { name: "data", type: "bytes" },
      { name: "nonce", type: "uint256" }
    ]
  };

  const message = {
    from,
    to,
    data,
    nonce
  };

  const typedData = {
    domain,
    types,
    primaryType: "MetaTransaction", 
    message
  };

  return await eth.signTypedData(from, typedData);
}

Signature Utilities

Signature Recovery and Verification

import { recover, hashMessage } from "web3-utils";

// Verify message signature
function verifyMessageSignature(message: string, signature: string, expectedSigner: Address): boolean {
  try {
    const recoveredAddress = recover(message, signature);
    return recoveredAddress.toLowerCase() === expectedSigner.toLowerCase();
  } catch (error) {
    console.error("Signature verification failed:", error);
    return false;
  }
}

// Verify EIP-712 signature (requires additional library like @ethersproject/hash)
async function verifyTypedDataSignature(
  typedData: Eip712TypedData,
  signature: string,
  expectedSigner: Address
): Promise<boolean> {
  try {
    // This would require implementing EIP-712 hash calculation
    // or using a library like ethers.js _TypedDataEncoder
    const digest = computeTypedDataHash(typedData);
    const recoveredAddress = recover(digest, signature);
    return recoveredAddress.toLowerCase() === expectedSigner.toLowerCase();
  } catch (error) {
    console.error("Typed data signature verification failed:", error);
    return false;
  }
}

Batch Signing Operations

// Sign multiple messages in batch
async function signMultipleMessages(
  messages: string[],
  signerAddress: Address
): Promise<SignatureObject[]> {
  const signatures = await Promise.all(
    messages.map(message => eth.sign(message, signerAddress))
  );
  
  return signatures;
}

// Sign multiple transactions in batch  
async function signMultipleTransactions(
  transactions: Transaction[],
  signerAddress: Address
): Promise<SignedTransactionInfoAPI[]> {
  // Add nonces if not present
  const baseNonce = await eth.getTransactionCount(signerAddress);
  
  const txsWithNonces = transactions.map((tx, index) => ({
    ...tx,
    from: signerAddress,
    nonce: tx.nonce ?? (baseNonce + index)
  }));

  const signedTxs = await Promise.all(
    txsWithNonces.map(tx => eth.signTransaction(tx))
  );
  
  return signedTxs;
}

Signature Format Conversion

// Convert between signature formats
function parseSignature(signature: string) {
  if (signature.startsWith('0x')) {
    signature = signature.slice(2);
  }
  
  const r = '0x' + signature.slice(0, 64);
  const s = '0x' + signature.slice(64, 128);
  const v = parseInt(signature.slice(128, 130), 16);
  
  return { r, s, v };
}

function combineSignature(r: string, s: string, v: number): string {
  const rHex = r.startsWith('0x') ? r.slice(2) : r;
  const sHex = s.startsWith('0x') ? s.slice(2) : s;
  const vHex = v.toString(16).padStart(2, '0');
  
  return '0x' + rHex + sHex + vHex;
}

Core Types

interface SignatureObject {
  messageHash: HexString32Bytes;
  r: HexString32Bytes;
  s: HexString32Bytes;
  v: HexString;
  signature: HexString;
}

interface SignedTransactionInfoAPI {
  messageHash: HexString32Bytes;
  r: HexString32Bytes;
  s: HexString32Bytes;
  v: HexString;
  rawTransaction: HexString;
  transactionHash: HexString32Bytes;
}

interface Eip712TypedData {
  domain: {
    name?: string;
    version?: string;
    chainId?: Numbers;
    verifyingContract?: Address;
    salt?: HexString32Bytes;
  };
  types: {
    [key: string]: Array<{
      name: string;
      type: string;
    }>;
  };
  primaryType: string;
  message: {
    [key: string]: any;
  };
}

interface Transaction {
  from: Address;
  to?: Address;
  value?: Numbers;
  gas?: Numbers;
  gasPrice?: Numbers;
  maxFeePerGas?: Numbers;
  maxPriorityFeePerGas?: Numbers;
  data?: Bytes;
  nonce?: Numbers;
  type?: Numbers;
  accessList?: AccessList;
  chainId?: Numbers;
}

type Address = HexString20Bytes;
type Numbers = HexString | number | bigint;
type Bytes = HexString;

Install with Tessl CLI

npx tessl i tessl/npm-web3-eth

docs

account-operations.md

blockchain-state.md

cryptographic-operations.md

event-monitoring.md

gas-fee-management.md

index.md

network-information.md

smart-contract-interaction.md

transaction-management.md

transaction-utilities.md

tile.json