0
# Data Validation
1
2
Matchers for validating Ethereum-specific data formats including addresses, private keys, and hex strings.
3
4
## Capabilities
5
6
### Hex String Equality
7
8
Tests if two hex strings are equal, handling case differences and 0x prefix variations.
9
10
```typescript { .api }
11
/**
12
* Tests hex string equality with normalization
13
* @param other - The hex string to compare against
14
* @returns void - assertion passes or throws
15
*/
16
hexEqual(other: string): void;
17
```
18
19
**Usage Examples:**
20
21
```typescript
22
import { expect } from "chai";
23
24
// Test hex string equality (case insensitive)
25
expect("0xabcdef").to.hexEqual("0xABCDEF");
26
expect("0x123456").to.hexEqual("0x123456");
27
28
// Works with or without 0x prefix
29
expect("abcdef").to.hexEqual("0xABCDEF");
30
expect("0x123456").to.hexEqual("123456");
31
32
// Test inequality
33
expect("0xabc123").to.not.hexEqual("0xdef456");
34
35
// Usage with contract addresses
36
const contractAddress = await contract.getAddress();
37
expect(contractAddress).to.hexEqual("0x742d35Cc6634C0532925a3b8D3d9C24cB2B05cC");
38
39
// Compare transaction hashes
40
const tx = await contract.someFunction();
41
expect(tx.hash).to.hexEqual(expectedHash);
42
```
43
44
### Ethereum Address Validation
45
46
Tests if a value is a valid Ethereum address format.
47
48
```typescript { .api }
49
/**
50
* Tests if value is a valid Ethereum address
51
* @returns void - assertion passes or throws
52
*/
53
properAddress: void;
54
```
55
56
**Usage Examples:**
57
58
```typescript
59
// Test valid addresses
60
expect("0x742d35Cc6634C0532925a3b8D3d9C24c").to.be.properAddress;
61
expect("0x0000000000000000000000000000000000000000").to.be.properAddress; // Zero address
62
expect("0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF").to.be.properAddress; // Mixed case
63
64
// Test invalid addresses
65
expect("0x123").to.not.be.properAddress; // Too short
66
expect("0xGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG").to.not.be.properAddress; // Invalid hex
67
expect("123456789012345678901234567890123456789012").to.not.be.properAddress; // No 0x prefix
68
expect("").to.not.be.properAddress; // Empty string
69
70
// Usage with dynamic addresses
71
const signerAddress = await signer.getAddress();
72
expect(signerAddress).to.be.properAddress;
73
74
const contractAddress = await ethers.getContractFactory("MyContract").then(f => f.deploy()).then(c => c.getAddress());
75
expect(contractAddress).to.be.properAddress;
76
```
77
78
### Private Key Validation
79
80
Tests if a value is a valid Ethereum private key format.
81
82
```typescript { .api }
83
/**
84
* Tests if value is a valid Ethereum private key
85
* @returns void - assertion passes or throws
86
*/
87
properPrivateKey: void;
88
```
89
90
**Usage Examples:**
91
92
```typescript
93
// Test valid private keys (64 hex characters)
94
expect("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef").to.be.properPrivateKey;
95
expect("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef").to.be.properPrivateKey; // Without 0x
96
97
// Test invalid private keys
98
expect("0x123").to.not.be.properPrivateKey; // Too short
99
expect("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdefg").to.not.be.properPrivateKey; // Invalid hex
100
expect("").to.not.be.properPrivateKey; // Empty string
101
102
// Usage in testing scenarios
103
const wallet = ethers.Wallet.createRandom();
104
expect(wallet.privateKey).to.be.properPrivateKey;
105
106
// Validate generated keys
107
const generatedKey = generatePrivateKey(); // Your key generation function
108
expect(generatedKey).to.be.properPrivateKey;
109
```
110
111
### Hex String Length Validation
112
113
Tests if a value is a valid hex string of a specific length.
114
115
```typescript { .api }
116
/**
117
* Tests if value is valid hex string of specific length
118
* @param length - Expected length in bytes (not hex characters)
119
* @returns void - assertion passes or throws
120
*/
121
properHex(length: number): void;
122
```
123
124
**Usage Examples:**
125
126
```typescript
127
// Test specific hex lengths (length is in bytes, not characters)
128
expect("0x1234").to.be.properHex(2); // 2 bytes = 4 hex characters
129
expect("0xabcdef123456").to.be.properHex(6); // 6 bytes = 12 hex characters
130
expect("0x" + "ff".repeat(32)).to.be.properHex(32); // 32 bytes = 64 hex characters
131
132
// Works without 0x prefix
133
expect("1234").to.be.properHex(2);
134
expect("abcdef123456").to.be.properHex(6);
135
136
// Test invalid lengths
137
expect("0x1234").to.not.be.properHex(3); // Wrong length
138
expect("0x123").to.not.be.properHex(2); // Odd number of hex characters
139
expect("0xGGGG").to.not.be.properHex(2); // Invalid hex characters
140
141
// Common Ethereum use cases
142
expect(transactionHash).to.be.properHex(32); // Transaction hashes are 32 bytes
143
expect(blockHash).to.be.properHex(32); // Block hashes are 32 bytes
144
expect(signature.r).to.be.properHex(32); // Signature components are 32 bytes
145
expect(signature.s).to.be.properHex(32);
146
147
// Smart contract testing
148
const merkleRoot = await contract.getMerkleRoot();
149
expect(merkleRoot).to.be.properHex(32); // Merkle roots are typically 32 bytes
150
151
const nonce = await contract.getNonce(user);
152
expect(ethers.toBeHex(nonce, 8)).to.be.properHex(8); // 8-byte nonce
153
```
154
155
## Advanced Validation Patterns
156
157
### Combined Validations
158
159
```typescript
160
// Validate address format and non-zero
161
const deployedAddress = await contract.getAddress();
162
expect(deployedAddress).to.be.properAddress;
163
expect(deployedAddress).to.not.hexEqual("0x0000000000000000000000000000000000000000");
164
165
// Validate transaction hash format
166
const tx = await contract.someFunction();
167
expect(tx.hash).to.be.properHex(32);
168
expect(tx.hash).to.match(/^0x[0-9a-fA-F]{64}$/); // Additional regex validation
169
```
170
171
### Data Structure Validation
172
173
```typescript
174
// Validate signature components
175
interface Signature {
176
r: string;
177
s: string;
178
v: number;
179
}
180
181
function validateSignature(sig: Signature) {
182
expect(sig.r).to.be.properHex(32);
183
expect(sig.s).to.be.properHex(32);
184
expect(sig.v).to.be.oneOf([27, 28]); // Standard Chai matcher
185
}
186
187
// Validate multi-field data
188
const accountData = await contract.getAccount(user);
189
expect(accountData.owner).to.be.properAddress;
190
expect(accountData.nonce).to.be.properHex(8);
191
expect(accountData.balance).to.be.properHex(32);
192
```
193
194
### Error Messages
195
196
The validation matchers provide clear error messages:
197
198
```typescript
199
// Address validation error: "Expected '0x123' to be a proper address"
200
// Private key error: "Expected '0x123' to be a proper private key"
201
// Hex length error: "Expected '0x1234' to be proper hex of length 4, but got length 2"
202
// Hex equality error: "Expected '0xabc' to equal '0xdef'"
203
```
204
205
## Input Handling
206
207
### Case Sensitivity
208
209
```typescript
210
// Hex equality is case insensitive
211
expect("0xabcdef").to.hexEqual("0xABCDEF"); // ✅ Passes
212
213
// Address validation accepts mixed case
214
expect("0xaBcDeF1234567890AbCdEf1234567890AbCdEf12").to.be.properAddress; // ✅ Passes
215
```
216
217
### Prefix Handling
218
219
```typescript
220
// All matchers handle 0x prefix gracefully
221
expect("abcdef").to.hexEqual("0xABCDEF"); // ✅ Passes
222
expect("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef").to.be.properPrivateKey; // ✅ Passes
223
expect("1234").to.be.properHex(2); // ✅ Passes
224
```
225
226
## Integration with Ethers.js
227
228
These matchers work seamlessly with ethers.js objects:
229
230
```typescript
231
// Works with ethers Wallet objects
232
const wallet = ethers.Wallet.createRandom();
233
expect(await wallet.getAddress()).to.be.properAddress;
234
expect(wallet.privateKey).to.be.properPrivateKey;
235
236
// Works with Contract objects
237
const contract = await ethers.getContractFactory("MyContract").then(f => f.deploy());
238
expect(await contract.getAddress()).to.be.properAddress;
239
240
// Works with transaction objects
241
const tx = await contract.someFunction();
242
expect(tx.hash).to.be.properHex(32);
243
```