0
# EIP-712 Structured Data
1
2
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.
3
4
## Capabilities
5
6
### Get Encoded EIP-712 Data
7
8
Gets the EIP-191 encoded message to sign from typed data object. Implements the EIP-712 standard for structured data hashing and signing.
9
10
```typescript { .api }
11
/**
12
* Gets EIP-191 encoded message from typed data for signing
13
* @param typedData - The EIP-712 typed data object
14
* @param hash - Whether to hash the message with Keccak256
15
* @returns The encoded message (hashed if hash=true)
16
*/
17
function getEncodedEip712Data(
18
typedData: Eip712TypedData,
19
hash?: boolean
20
): string;
21
```
22
23
**Usage Examples:**
24
25
```typescript
26
import { getEncodedEip712Data } from "web3-eth-abi";
27
28
// Define EIP-712 typed data
29
const typedData = {
30
types: {
31
EIP712Domain: [
32
{ name: "name", type: "string" },
33
{ name: "version", type: "string" },
34
{ name: "chainId", type: "uint256" },
35
{ name: "verifyingContract", type: "address" }
36
],
37
Person: [
38
{ name: "name", type: "string" },
39
{ name: "wallet", type: "address" }
40
],
41
Mail: [
42
{ name: "from", type: "Person" },
43
{ name: "to", type: "Person" },
44
{ name: "contents", type: "string" }
45
]
46
},
47
primaryType: "Mail",
48
domain: {
49
name: "Ether Mail",
50
version: "1",
51
chainId: 1,
52
verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
53
},
54
message: {
55
from: {
56
name: "Cow",
57
wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"
58
},
59
to: {
60
name: "Bob",
61
wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
62
},
63
contents: "Hello, Bob!"
64
}
65
};
66
67
// Get encoded message for signing (not hashed)
68
const encodedMessage = getEncodedEip712Data(typedData, false);
69
console.log(encodedMessage);
70
// 0x1901... (EIP-191 prefix + domain separator + message hash)
71
72
// Get hashed message for signing
73
const hashedMessage = getEncodedEip712Data(typedData, true);
74
console.log(hashedMessage);
75
// 0x... (Keccak256 hash of the encoded message)
76
77
// Use with eth_signTypedData_v4
78
// The hashed message can be used directly with wallet signing methods
79
```
80
81
## EIP-712 Structure
82
83
### Domain Separator
84
85
The domain separator ensures that signatures are specific to a particular application and chain:
86
87
```typescript
88
interface EIP712Domain {
89
name?: string; // Human readable name of signing domain
90
version?: string; // Current major version of signing domain
91
chainId?: number; // EIP-155 chain id
92
verifyingContract?: string; // Address of contract that will verify signature
93
salt?: string; // Disambiguating salt for protocol
94
}
95
```
96
97
### Typed Data Structure
98
99
```typescript
100
interface Eip712TypedData {
101
types: Record<string, Array<{ name: string; type: string }>>;
102
primaryType: string;
103
domain: Record<string, unknown>;
104
message: Record<string, unknown>;
105
}
106
```
107
108
### Type Definitions
109
110
Custom types are defined in the `types` object, with each type specifying its fields and their types:
111
112
```typescript
113
const types = {
114
Person: [
115
{ name: "name", type: "string" },
116
{ name: "wallet", type: "address" }
117
],
118
Mail: [
119
{ name: "from", type: "Person" }, // References Person type
120
{ name: "to", type: "Person" },
121
{ name: "contents", type: "string" }
122
]
123
};
124
```
125
126
## Advanced Usage Examples
127
128
### Token Permit (ERC-2612)
129
130
```typescript
131
const permitTypedData = {
132
types: {
133
EIP712Domain: [
134
{ name: "name", type: "string" },
135
{ name: "version", type: "string" },
136
{ name: "chainId", type: "uint256" },
137
{ name: "verifyingContract", type: "address" }
138
],
139
Permit: [
140
{ name: "owner", type: "address" },
141
{ name: "spender", type: "address" },
142
{ name: "value", type: "uint256" },
143
{ name: "nonce", type: "uint256" },
144
{ name: "deadline", type: "uint256" }
145
]
146
},
147
primaryType: "Permit",
148
domain: {
149
name: "MyToken",
150
version: "1",
151
chainId: 1,
152
verifyingContract: "0x1234567890123456789012345678901234567890"
153
},
154
message: {
155
owner: "0xowner...",
156
spender: "0xspender...",
157
value: "1000000000000000000", // 1 token
158
nonce: 0,
159
deadline: 1700000000
160
}
161
};
162
163
const permitHash = getEncodedEip712Data(permitTypedData, true);
164
```
165
166
### Order Signing (DEX/Marketplace)
167
168
```typescript
169
const orderTypedData = {
170
types: {
171
EIP712Domain: [
172
{ name: "name", type: "string" },
173
{ name: "version", type: "string" },
174
{ name: "chainId", type: "uint256" },
175
{ name: "verifyingContract", type: "address" }
176
],
177
Order: [
178
{ name: "maker", type: "address" },
179
{ name: "taker", type: "address" },
180
{ name: "tokenA", type: "address" },
181
{ name: "tokenB", type: "address" },
182
{ name: "amountA", type: "uint256" },
183
{ name: "amountB", type: "uint256" },
184
{ name: "expiry", type: "uint256" },
185
{ name: "nonce", type: "uint256" }
186
]
187
},
188
primaryType: "Order",
189
domain: {
190
name: "MyDEX",
191
version: "1",
192
chainId: 1,
193
verifyingContract: "0xDEX_CONTRACT_ADDRESS"
194
},
195
message: {
196
maker: "0xmaker...",
197
taker: "0x0000000000000000000000000000000000000000", // Any taker
198
tokenA: "0xTokenA...",
199
tokenB: "0xTokenB...",
200
amountA: "1000000000000000000",
201
amountB: "500000000000000000",
202
expiry: 1700000000,
203
nonce: 1
204
}
205
};
206
207
const orderHash = getEncodedEip712Data(orderTypedData, true);
208
```
209
210
## Implementation Details
211
212
### Encoding Process
213
214
1. **Type Hash**: Calculate keccak256 of the encoded type definition
215
2. **Struct Hash**: Calculate keccak256 of type hash + encoded values
216
3. **Domain Separator**: Calculate keccak256 of domain type hash + domain values
217
4. **Final Message**: EIP-191 prefix + domain separator + message hash
218
219
### Array Handling
220
221
Arrays in EIP-712 are encoded by hashing each element recursively and then hashing the concatenated hashes.
222
223
### String and Bytes Handling
224
225
Strings and dynamic bytes are hashed using keccak256 when used in structured data.
226
227
## Types
228
229
```typescript { .api }
230
interface Eip712TypedData {
231
types: Record<string, Array<{ name: string; type: string }>>;
232
primaryType: string;
233
domain: Record<string, unknown>;
234
message: Record<string, unknown>;
235
}
236
237
interface EIP712Domain {
238
name?: string;
239
version?: string;
240
chainId?: number;
241
verifyingContract?: string;
242
salt?: string;
243
}
244
```