or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

account-operations.mdblockchain-state.mdcryptographic-operations.mdevent-monitoring.mdgas-fee-management.mdindex.mdnetwork-information.mdsmart-contract-interaction.mdtransaction-management.mdtransaction-utilities.md

cryptographic-operations.mddocs/

0

# Cryptographic Operations

1

2

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.

3

4

## Message Signing

5

6

### sign

7

8

Signs arbitrary messages using an account's private key.

9

10

```typescript { .api }

11

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

12

```

13

14

**Parameters:**

15

- `message`: The message to sign (hex string or bytes)

16

- `addressOrIndex`: Account address or wallet index to sign with

17

- `returnFormat`: Output format configuration

18

19

**Usage Example:**

20

```typescript

21

// Sign a simple message

22

const message = "Hello, Ethereum!";

23

const signature = await eth.sign(message, "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E");

24

25

console.log("Message signature:", {

26

messageHash: signature.messageHash,

27

r: signature.r,

28

s: signature.s,

29

v: signature.v,

30

signature: signature.signature

31

});

32

33

// Sign hex-encoded data

34

const hexMessage = "0x48656c6c6f2c20457468657265756d21"; // "Hello, Ethereum!" in hex

35

const hexSignature = await eth.sign(hexMessage, "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E");

36

37

// Verify signature (using web3-utils)

38

import { recover } from "web3-utils";

39

const recoveredAddress = recover(message, signature.signature);

40

console.log("Signature verification:", recoveredAddress === "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E");

41

```

42

43

## Transaction Signing

44

45

### signTransaction

46

47

Signs a transaction without broadcasting it to the network.

48

49

```typescript { .api }

50

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

51

```

52

53

**Usage Example:**

54

```typescript

55

// Sign a transaction for later broadcast

56

const transaction = {

57

from: "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E",

58

to: "0x8ba1f109551bD432803012645Hac136c1c1b6c5E",

59

value: "1000000000000000000", // 1 ETH

60

gas: "21000",

61

gasPrice: "20000000000", // 20 Gwei

62

nonce: await eth.getTransactionCount("0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E")

63

};

64

65

const signedTx = await eth.signTransaction(transaction);

66

console.log("Signed transaction:", {

67

messageHash: signedTx.messageHash,

68

r: signedTx.r,

69

s: signedTx.s,

70

v: signedTx.v,

71

rawTransaction: signedTx.rawTransaction

72

});

73

74

// Broadcast the signed transaction later

75

const receipt = await eth.sendSignedTransaction(signedTx.rawTransaction);

76

```

77

78

### EIP-1559 Transaction Signing

79

80

```typescript

81

// Sign EIP-1559 transaction

82

const eip1559Transaction = {

83

from: "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E",

84

to: "0x8ba1f109551bD432803012645Hac136c1c1b6c5E",

85

value: "1000000000000000000",

86

gas: "21000",

87

maxFeePerGas: "30000000000", // 30 Gwei

88

maxPriorityFeePerGas: "2000000000", // 2 Gwei

89

nonce: await eth.getTransactionCount("0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E"),

90

type: 2 // EIP-1559

91

};

92

93

const signed1559Tx = await eth.signTransaction(eip1559Transaction);

94

```

95

96

## EIP-712 Typed Data Signing

97

98

### signTypedData

99

100

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

101

102

```typescript { .api }

103

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

104

```

105

106

**Parameters:**

107

- `address`: Signer's address

108

- `typedData`: EIP-712 structured data object

109

- `useLegacy`: Use legacy signing format (default: false)

110

- `returnFormat`: Output format configuration

111

112

**Usage Example:**

113

```typescript

114

// Define EIP-712 domain and types

115

const domain = {

116

name: "MyDApp",

117

version: "1",

118

chainId: 1,

119

verifyingContract: "0x1234567890123456789012345678901234567890"

120

};

121

122

const types = {

123

Person: [

124

{ name: "name", type: "string" },

125

{ name: "wallet", type: "address" }

126

],

127

Mail: [

128

{ name: "from", type: "Person" },

129

{ name: "to", type: "Person" },

130

{ name: "contents", type: "string" }

131

]

132

};

133

134

const message = {

135

from: {

136

name: "Alice",

137

wallet: "0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E"

138

},

139

to: {

140

name: "Bob",

141

wallet: "0x8ba1f109551bD432803012645Hac136c1c1b6c5E"

142

},

143

contents: "Hello Bob!"

144

};

145

146

const typedData = {

147

domain,

148

types,

149

primaryType: "Mail",

150

message

151

};

152

153

// Sign the typed data

154

const signature = await eth.signTypedData(

155

"0x742d35Cc6634C0532925a3b8D7389Fc3C1b6c5E",

156

typedData

157

);

158

159

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

160

```

161

162

### Common EIP-712 Use Cases

163

164

#### ERC-20 Permit Signing

165

166

```typescript

167

// Sign ERC-20 permit for gasless approvals

168

async function signPermit(

169

tokenAddress: Address,

170

owner: Address,

171

spender: Address,

172

value: string,

173

deadline: number,

174

nonce: number

175

) {

176

const domain = {

177

name: "Token Name", // Get from token contract

178

version: "1",

179

chainId: await eth.getChainId(),

180

verifyingContract: tokenAddress

181

};

182

183

const types = {

184

Permit: [

185

{ name: "owner", type: "address" },

186

{ name: "spender", type: "address" },

187

{ name: "value", type: "uint256" },

188

{ name: "nonce", type: "uint256" },

189

{ name: "deadline", type: "uint256" }

190

]

191

};

192

193

const message = {

194

owner,

195

spender,

196

value,

197

nonce,

198

deadline

199

};

200

201

const typedData = {

202

domain,

203

types,

204

primaryType: "Permit",

205

message

206

};

207

208

return await eth.signTypedData(owner, typedData);

209

}

210

```

211

212

#### MetaTransaction Signing

213

214

```typescript

215

// Sign meta-transaction for gasless execution

216

async function signMetaTransaction(

217

from: Address,

218

to: Address,

219

data: string,

220

nonce: number,

221

relayerAddress: Address

222

) {

223

const domain = {

224

name: "MetaTransactionRelay",

225

version: "1",

226

chainId: await eth.getChainId(),

227

verifyingContract: relayerAddress

228

};

229

230

const types = {

231

MetaTransaction: [

232

{ name: "from", type: "address" },

233

{ name: "to", type: "address" },

234

{ name: "data", type: "bytes" },

235

{ name: "nonce", type: "uint256" }

236

]

237

};

238

239

const message = {

240

from,

241

to,

242

data,

243

nonce

244

};

245

246

const typedData = {

247

domain,

248

types,

249

primaryType: "MetaTransaction",

250

message

251

};

252

253

return await eth.signTypedData(from, typedData);

254

}

255

```

256

257

## Signature Utilities

258

259

### Signature Recovery and Verification

260

261

```typescript

262

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

263

264

// Verify message signature

265

function verifyMessageSignature(message: string, signature: string, expectedSigner: Address): boolean {

266

try {

267

const recoveredAddress = recover(message, signature);

268

return recoveredAddress.toLowerCase() === expectedSigner.toLowerCase();

269

} catch (error) {

270

console.error("Signature verification failed:", error);

271

return false;

272

}

273

}

274

275

// Verify EIP-712 signature (requires additional library like @ethersproject/hash)

276

async function verifyTypedDataSignature(

277

typedData: Eip712TypedData,

278

signature: string,

279

expectedSigner: Address

280

): Promise<boolean> {

281

try {

282

// This would require implementing EIP-712 hash calculation

283

// or using a library like ethers.js _TypedDataEncoder

284

const digest = computeTypedDataHash(typedData);

285

const recoveredAddress = recover(digest, signature);

286

return recoveredAddress.toLowerCase() === expectedSigner.toLowerCase();

287

} catch (error) {

288

console.error("Typed data signature verification failed:", error);

289

return false;

290

}

291

}

292

```

293

294

### Batch Signing Operations

295

296

```typescript

297

// Sign multiple messages in batch

298

async function signMultipleMessages(

299

messages: string[],

300

signerAddress: Address

301

): Promise<SignatureObject[]> {

302

const signatures = await Promise.all(

303

messages.map(message => eth.sign(message, signerAddress))

304

);

305

306

return signatures;

307

}

308

309

// Sign multiple transactions in batch

310

async function signMultipleTransactions(

311

transactions: Transaction[],

312

signerAddress: Address

313

): Promise<SignedTransactionInfoAPI[]> {

314

// Add nonces if not present

315

const baseNonce = await eth.getTransactionCount(signerAddress);

316

317

const txsWithNonces = transactions.map((tx, index) => ({

318

...tx,

319

from: signerAddress,

320

nonce: tx.nonce ?? (baseNonce + index)

321

}));

322

323

const signedTxs = await Promise.all(

324

txsWithNonces.map(tx => eth.signTransaction(tx))

325

);

326

327

return signedTxs;

328

}

329

```

330

331

## Signature Format Conversion

332

333

```typescript

334

// Convert between signature formats

335

function parseSignature(signature: string) {

336

if (signature.startsWith('0x')) {

337

signature = signature.slice(2);

338

}

339

340

const r = '0x' + signature.slice(0, 64);

341

const s = '0x' + signature.slice(64, 128);

342

const v = parseInt(signature.slice(128, 130), 16);

343

344

return { r, s, v };

345

}

346

347

function combineSignature(r: string, s: string, v: number): string {

348

const rHex = r.startsWith('0x') ? r.slice(2) : r;

349

const sHex = s.startsWith('0x') ? s.slice(2) : s;

350

const vHex = v.toString(16).padStart(2, '0');

351

352

return '0x' + rHex + sHex + vHex;

353

}

354

```

355

356

## Core Types

357

358

```typescript { .api }

359

interface SignatureObject {

360

messageHash: HexString32Bytes;

361

r: HexString32Bytes;

362

s: HexString32Bytes;

363

v: HexString;

364

signature: HexString;

365

}

366

367

interface SignedTransactionInfoAPI {

368

messageHash: HexString32Bytes;

369

r: HexString32Bytes;

370

s: HexString32Bytes;

371

v: HexString;

372

rawTransaction: HexString;

373

transactionHash: HexString32Bytes;

374

}

375

376

interface Eip712TypedData {

377

domain: {

378

name?: string;

379

version?: string;

380

chainId?: Numbers;

381

verifyingContract?: Address;

382

salt?: HexString32Bytes;

383

};

384

types: {

385

[key: string]: Array<{

386

name: string;

387

type: string;

388

}>;

389

};

390

primaryType: string;

391

message: {

392

[key: string]: any;

393

};

394

}

395

396

interface Transaction {

397

from: Address;

398

to?: Address;

399

value?: Numbers;

400

gas?: Numbers;

401

gasPrice?: Numbers;

402

maxFeePerGas?: Numbers;

403

maxPriorityFeePerGas?: Numbers;

404

data?: Bytes;

405

nonce?: Numbers;

406

type?: Numbers;

407

accessList?: AccessList;

408

chainId?: Numbers;

409

}

410

411

type Address = HexString20Bytes;

412

type Numbers = HexString | number | bigint;

413

type Bytes = HexString;

414

```