Sign typed data

This guide will teach you how to sign EIP-712 typed data with your Smart Wallet. Typed data signing provides a more structured and secure way to sign complex data compared to plain text messages.

Prerequisites

  • API key from your dashboard
  • A Smart Wallet with an associated signer

When using EIP-7702, your account must be delegated before signatures will be valid. Send at least one transaction to delegate your account first.

What is typed data signing?

EIP-712 typed data signing allows users to:

  • Sign structured data with clear type definitions
  • Improve user experience with readable signature requests
  • Enhance security through type safety and domain separation

Typed data follows the EIP-712 standard, which provides a way to encode structured data for signing.

Implementation

Required SDK version: ^v4.59.1

See the signTypedData SDK reference for full descriptions of the parameters used in the following example.

1import { client, signer } from "./client";
2
3const signerAddress = await signer.getAddress();
4
5// Sign typed data
6const typedData = {
7 domain: {
8 name: "MyDApp",
9 version: "1",
10 chainId: 1,
11 verifyingContract: "0x...",
12 },
13 types: {
14 Auth: [
15 { name: "user", type: "address" },
16 { name: "nonce", type: "uint256" },
17 { name: "timestamp", type: "uint256" },
18 ],
19 },
20 primaryType: "Auth",
21 message: {
22 user: signerAddress,
23 nonce: 12345,
24 timestamp: Date.now(),
25 },
26} as const;
27
28const signature = await client.signTypedData({
29 ...typedData,
30 account: signerAddress,
31});
32
33console.log("Typed data signature:", signature);

Typed data structure

EIP-712 typed data consists of four main components:

Domain

The domain provides context and prevents signature reuse across different dApps:

1const domain = {
2 name: "Example DApp",
3 version: "1",
4 chainId: 1,
5 verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
6};

Types

Define the structure of your data:

1const types = {
2 Person: [
3 { name: "name", type: "string" },
4 { name: "wallet", type: "address" },
5 ],
6 Mail: [
7 { name: "from", type: "Person" },
8 { name: "to", type: "Person" },
9 { name: "contents", type: "string" },
10 ],
11};

Primary type

Specify which type is the main type being signed:

1const primaryType = "Mail";

Message

The actual data to sign:

1const message = {
2 from: {
3 name: "Alice",
4 wallet: "0xAaAaAaAaAaAaAaAaAaAAAAAAAAaaaAaAaAaaAaAa",
5 },
6 to: {
7 name: "Bob",
8 wallet: "0xBbBbBbBbBbBbBbBbBbBBBBBBBBbbBbBbBbbBbBb",
9 },
10 contents: "Hello, Bob!",
11};

Next steps

Build more:

Troubleshooting: