or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

contract-deployment.mdcontract-management.mdencoding-utilities.mdevent-handling.mdindex.mdmethod-execution.md

event-handling.mddocs/

0

# Event Handling

1

2

Event subscription, filtering, and log processing with typed event data based on contract ABI definitions.

3

4

## Capabilities

5

6

### Event Subscription

7

8

Subscribe to contract events using the dynamically generated `events` property.

9

10

```typescript { .api }

11

class Contract<Abi extends ContractAbi> {

12

/** Dynamically generated events based on contract ABI */

13

readonly events: ContractEventsInterface<Abi>;

14

15

/**

16

* Gets past events for this contract from blockchain history

17

* @param eventName - The event name or 'allEvents' to get all events

18

* @param filter - Filter options with fromBlock, toBlock, and indexed parameter filters

19

* @returns Array of past event objects matching the criteria

20

*/

21

getPastEvents(eventName?: keyof ContractEvents<Abi> | 'allEvents'): Promise<EventLog[]>;

22

getPastEvents(filter: Omit<Filter, 'address'>): Promise<EventLog[]>;

23

getPastEvents(

24

eventName: keyof ContractEvents<Abi> | 'allEvents',

25

filter: Omit<Filter, 'address'>

26

): Promise<EventLog[]>;

27

}

28

29

type ContractEventsInterface<Abi extends ContractAbi> = {

30

[Name in keyof ContractEvents<Abi> | 'allEvents']: ContractBoundEvent;

31

} & {

32

/** Allow access by event signature */

33

[key: string]: ContractBoundEvent;

34

};

35

36

/**

37

* Event subscription function

38

* @param options - Event filtering and subscription options

39

* @returns ContractLogsSubscription for managing the subscription

40

*/

41

type ContractBoundEvent = (options?: ContractEventOptions) => ContractLogsSubscription;

42

```

43

44

### Event Options

45

46

Options for filtering and configuring event subscriptions.

47

48

```typescript { .api }

49

interface ContractEventOptions {

50

/**

51

* Filter events by indexed parameters

52

* Example: { filter: { myNumber: [12, 13] } } means all events where myNumber is 12 or 13

53

*/

54

filter?: Record<string, unknown>;

55

56

/**

57

* The block number from which to get events on

58

* Can use 'earliest', 'latest', 'pending', 'safe', 'finalized' or specific block number

59

*/

60

fromBlock?: BlockNumberOrTag;

61

62

/**

63

* Manually set the topics for the event filter

64

* If given, the filter property and event signature (topic[0]) will not be set automatically

65

*/

66

topics?: string[];

67

}

68

```

69

70

### ContractLogsSubscription

71

72

Subscription class for managing event subscriptions with Web3 subscription interface.

73

74

```typescript { .api }

75

/**

76

* ContractLogsSubscription for contract event logs

77

*

78

* Supported events:

79

* - connected: Emitted when subscription is connected

80

* - data: Fires on each incoming event with event object

81

* - changed: Fires on each event removed from blockchain (has 'removed: true')

82

* - error: Fires on each error

83

*/

84

class ContractLogsSubscription extends Web3Subscription<

85

EventLog,

86

EthExecutionAPI

87

> {

88

constructor(

89

args: {

90

address?: Address;

91

topics?: string[];

92

abi?: ContractAbiWithSignature;

93

jsonInterface?: ContractAbiWithSignature;

94

},

95

options: {

96

subscriptionManager: Web3SubscriptionManager;

97

returnFormat?: DataFormat;

98

}

99

);

100

}

101

102

// Deprecated alias (use ContractLogsSubscription instead)

103

const LogsSubscription = ContractLogsSubscription;

104

```

105

106

### Event Log Structure

107

108

Structure of event logs returned by subscriptions and past event queries.

109

110

```typescript { .api }

111

interface EventLog {

112

/** Event name */

113

event?: string;

114

/** Event signature hash */

115

signature?: HexString;

116

/** Contract address that emitted the event */

117

address: string;

118

/** Indexed and non-indexed event parameters */

119

returnValues: Record<string, unknown>;

120

/** Array of log topics */

121

topics: string[];

122

/** Raw log data */

123

data: string;

124

/** Block number where event was emitted */

125

blockNumber: number;

126

/** Block hash where event was emitted */

127

blockHash: string;

128

/** Transaction hash that triggered the event */

129

transactionHash: string;

130

/** Transaction index in the block */

131

transactionIndex: number;

132

/** Log index in the block */

133

logIndex: number;

134

/** True if event was removed from blockchain */

135

removed?: boolean;

136

}

137

```

138

139

## Usage Examples

140

141

### Basic Event Subscription

142

143

```typescript

144

import { Contract } from "web3-eth-contract";

145

146

const abi = [

147

{

148

anonymous: false,

149

inputs: [

150

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

151

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

152

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

153

],

154

name: "Transfer",

155

type: "event"

156

},

157

{

158

anonymous: false,

159

inputs: [

160

{ indexed: false, name: "newValue", type: "uint256" }

161

],

162

name: "ValueChanged",

163

type: "event"

164

}

165

] as const;

166

167

const contract = new Contract(abi, contractAddress);

168

169

// Subscribe to specific event

170

const subscription = await contract.events.Transfer();

171

172

subscription.on('connected', (subscriptionId) => {

173

console.log('Subscription connected:', subscriptionId);

174

});

175

176

subscription.on('data', (event) => {

177

console.log('Transfer event:', {

178

from: event.returnValues.from,

179

to: event.returnValues.to,

180

value: event.returnValues.value,

181

blockNumber: event.blockNumber,

182

transactionHash: event.transactionHash

183

});

184

});

185

186

subscription.on('changed', (event) => {

187

console.log('Event removed (chain reorganization):', event);

188

});

189

190

subscription.on('error', (error) => {

191

console.error('Subscription error:', error);

192

});

193

```

194

195

### Event Filtering

196

197

```typescript

198

// Filter events by indexed parameters

199

const filteredSubscription = await contract.events.Transfer({

200

filter: {

201

from: "0x1234567890123456789012345678901234567890",

202

to: ["0xabcd...", "0xefgh..."] // Multiple values act as OR

203

},

204

fromBlock: 'latest'

205

});

206

207

filteredSubscription.on('data', (event) => {

208

console.log('Filtered transfer:', event.returnValues);

209

});

210

211

// Filter with specific block range

212

const historicalSubscription = await contract.events.ValueChanged({

213

fromBlock: 1000000,

214

// toBlock: 2000000 // Note: subscriptions don't support toBlock

215

});

216

```

217

218

### All Events Subscription

219

220

```typescript

221

// Subscribe to all contract events

222

const allEventsSubscription = await contract.events.allEvents({

223

fromBlock: 'latest'

224

});

225

226

allEventsSubscription.on('data', (event) => {

227

console.log('Event received:', {

228

eventName: event.event,

229

data: event.returnValues,

230

block: event.blockNumber

231

});

232

233

// Handle different event types

234

switch (event.event) {

235

case 'Transfer':

236

console.log('Transfer:', event.returnValues.from, '->', event.returnValues.to);

237

break;

238

case 'ValueChanged':

239

console.log('Value changed to:', event.returnValues.newValue);

240

break;

241

default:

242

console.log('Unknown event:', event.event);

243

}

244

});

245

```

246

247

### Manual Topic Filtering

248

249

```typescript

250

// Advanced filtering with manual topics

251

const manualSubscription = await contract.events.Transfer({

252

topics: [

253

null, // Event signature (automatically filled)

254

"0x1234567890123456789012345678901234567890", // from address

255

null // to address (any)

256

]

257

});

258

```

259

260

### Subscription Management

261

262

```typescript

263

// Store subscription reference

264

let transferSubscription: ContractLogsSubscription;

265

266

async function startEventListening() {

267

transferSubscription = await contract.events.Transfer();

268

269

transferSubscription.on('data', handleTransferEvent);

270

transferSubscription.on('error', handleError);

271

}

272

273

async function stopEventListening() {

274

if (transferSubscription) {

275

await transferSubscription.unsubscribe();

276

console.log('Unsubscribed from Transfer events');

277

}

278

}

279

280

function handleTransferEvent(event: EventLog) {

281

console.log('Transfer event received:', event);

282

}

283

284

function handleError(error: Error) {

285

console.error('Event subscription error:', error);

286

}

287

288

// Clean up on application exit

289

process.on('SIGINT', async () => {

290

await stopEventListening();

291

process.exit();

292

});

293

```

294

295

### Getting Past Events

296

297

```typescript

298

// Get historical events (not part of subscription)

299

// Note: This uses contract.getPastEvents() method

300

const pastEvents = await contract.getPastEvents('Transfer', {

301

filter: {

302

from: "0x1234567890123456789012345678901234567890"

303

},

304

fromBlock: 1000000,

305

toBlock: 2000000

306

});

307

308

console.log(`Found ${pastEvents.length} past Transfer events`);

309

pastEvents.forEach((event, index) => {

310

console.log(`Event ${index + 1}:`, {

311

from: event.returnValues.from,

312

to: event.returnValues.to,

313

value: event.returnValues.value,

314

block: event.blockNumber

315

});

316

});

317

```

318

319

### Error Handling

320

321

```typescript

322

async function subscribeWithErrorHandling() {

323

try {

324

const subscription = await contract.events.Transfer({

325

fromBlock: 'latest'

326

});

327

328

subscription.on('data', (event) => {

329

try {

330

processEvent(event);

331

} catch (error) {

332

console.error('Error processing event:', error);

333

}

334

});

335

336

subscription.on('error', (error) => {

337

console.error('Subscription error:', error);

338

339

// Attempt to resubscribe after delay

340

setTimeout(async () => {

341

try {

342

await subscribeWithErrorHandling();

343

} catch (reconnectError) {

344

console.error('Failed to reconnect:', reconnectError);

345

}

346

}, 5000);

347

});

348

349

} catch (error) {

350

console.error('Failed to create subscription:', error);

351

}

352

}

353

354

function processEvent(event: EventLog) {

355

// Your event processing logic

356

console.log('Processing event:', event.event);

357

}

358

```

359

360

### Multiple Event Types

361

362

```typescript

363

// Subscribe to multiple specific events

364

const events = ['Transfer', 'Approval', 'ValueChanged'] as const;

365

366

const subscriptions = await Promise.all(

367

events.map(eventName => contract.events[eventName]({

368

fromBlock: 'latest'

369

}))

370

);

371

372

subscriptions.forEach((subscription, index) => {

373

subscription.on('data', (event) => {

374

console.log(`${events[index]} event:`, event.returnValues);

375

});

376

});

377

378

// Cleanup all subscriptions

379

async function cleanup() {

380

await Promise.all(

381

subscriptions.map(sub => sub.unsubscribe())

382

);

383

}

384

```

385

386

## Constants

387

388

```typescript { .api }

389

// Special constants for event handling (re-exported from web3-eth)

390

const ALL_EVENTS: string;

391

const ALL_EVENTS_ABI: AbiEventFragment;

392

```