0
# Atomic Batch Transactions
1
2
EIP-5792 atomic batch transaction support for executing multiple operations as a single unit. This module provides comprehensive functionality for atomic batch transactions, allowing multiple contract calls to be executed together with guaranteed atomicity.
3
4
## Capabilities
5
6
### useSendCalls
7
8
Hook to send multiple calls atomically using EIP-5792 batch transaction standard.
9
10
```typescript { .api }
11
/**
12
* Hook to send multiple calls atomically
13
* @param parameters - Atomic batch calls configuration with mutation callbacks
14
* @returns Send calls mutation with batch transaction state
15
*/
16
function useSendCalls<config = Config, context = unknown>(
17
parameters?: UseSendCallsParameters<config, context>
18
): UseSendCallsReturnType<config, context>;
19
20
interface UseSendCallsParameters<config = Config, context = unknown> {
21
config?: Config | config;
22
mutation?: {
23
onMutate?: (variables: SendCallsVariables) => Promise<context> | context;
24
onError?: (error: SendCallsErrorType, variables: SendCallsVariables, context?: context) => Promise<void> | void;
25
onSuccess?: (data: SendCallsData, variables: SendCallsVariables, context?: context) => Promise<void> | void;
26
onSettled?: (data?: SendCallsData, error?: SendCallsErrorType, variables?: SendCallsVariables, context?: context) => Promise<void> | void;
27
};
28
}
29
30
interface UseSendCallsReturnType<config = Config, context = unknown> {
31
/** Send atomic batch calls */
32
sendCalls: (variables: SendCallsVariables, options?: SendCallsMutateOptions) => void;
33
/** Async version of sendCalls */
34
sendCallsAsync: (variables: SendCallsVariables, options?: SendCallsMutateAsyncOptions) => Promise<SendCallsData>;
35
/** Batch transaction data */
36
data?: SendCallsData;
37
/** Send calls error */
38
error: SendCallsErrorType | null;
39
/** Send calls status flags */
40
isError: boolean;
41
isIdle: boolean;
42
isPending: boolean;
43
isSuccess: boolean;
44
/** Reset send calls state */
45
reset: () => void;
46
/** Current status */
47
status: 'error' | 'idle' | 'pending' | 'success';
48
/** Additional variables */
49
variables?: SendCallsVariables;
50
}
51
52
interface SendCallsVariables {
53
/** Array of calls to execute atomically */
54
calls: Call[];
55
/** Batch execution capabilities */
56
capabilities?: WalletCapabilities;
57
/** Chain ID for the batch */
58
chainId?: number;
59
/** Version of the batch call standard */
60
version?: string;
61
}
62
63
interface Call {
64
/** Target contract address */
65
to?: Address;
66
/** Call data */
67
data?: Hex;
68
/** Value to send with call */
69
value?: bigint;
70
/** Gas limit for this call */
71
gas?: bigint;
72
/** Chain ID for this specific call */
73
chainId?: number;
74
}
75
76
interface SendCallsData {
77
/** Batch identifier */
78
id: string;
79
}
80
```
81
82
**Usage Example:**
83
84
```typescript
85
import { useSendCalls, useAccount } from "wagmi";
86
import { encodeFunctionData, erc20Abi } from "viem";
87
88
function BatchTransfer() {
89
const { address } = useAccount();
90
const { sendCalls, data: batchId, isPending } = useSendCalls();
91
92
const handleBatchTransfer = () => {
93
if (!address) return;
94
95
// Encode transfer calls
96
const transferCall1 = encodeFunctionData({
97
abi: erc20Abi,
98
functionName: 'transfer',
99
args: ['0x742d35Cc6634C0532925a3b8D', 1000000000000000000n], // 1 token
100
});
101
102
const transferCall2 = encodeFunctionData({
103
abi: erc20Abi,
104
functionName: 'transfer',
105
args: ['0x8ba1f109551bD432803012645Hac136c', 500000000000000000n], // 0.5 tokens
106
});
107
108
sendCalls({
109
calls: [
110
{
111
to: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
112
data: transferCall1,
113
},
114
{
115
to: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
116
data: transferCall2,
117
},
118
],
119
});
120
};
121
122
return (
123
<div>
124
<button onClick={handleBatchTransfer} disabled={!address || isPending}>
125
{isPending ? 'Sending Batch...' : 'Send Batch Transfers'}
126
</button>
127
{batchId && <p>Batch ID: {batchId}</p>}
128
</div>
129
);
130
}
131
```
132
133
### useCallsStatus
134
135
Hook to check the status of batched calls by their batch ID.
136
137
```typescript { .api }
138
/**
139
* Hook to check status of batched calls
140
* @param parameters - Calls status query parameters
141
* @returns Current status of the batched calls
142
*/
143
function useCallsStatus<config = Config, selectData = UseCallsStatusReturnType>(
144
parameters: UseCallsStatusParameters<config, selectData>
145
): UseCallsStatusReturnType<selectData>;
146
147
interface UseCallsStatusParameters<config = Config, selectData = UseCallsStatusReturnType> {
148
/** Batch ID to check status for */
149
id: string;
150
/** Chain ID where batch was submitted */
151
chainId?: config['chains'][number]['id'];
152
config?: Config | config;
153
query?: {
154
enabled?: boolean;
155
staleTime?: number;
156
gcTime?: number;
157
refetchInterval?: number;
158
select?: (data: UseCallsStatusReturnType) => selectData;
159
};
160
}
161
162
interface UseCallsStatusReturnType {
163
/** Current batch status */
164
status: 'PENDING' | 'CONFIRMED' | 'FAILED';
165
/** Individual call receipts */
166
receipts?: CallReceipt[];
167
}
168
169
interface CallReceipt {
170
/** Transaction hash for this call */
171
transactionHash: Hash;
172
/** Block hash */
173
blockHash: Hash;
174
/** Block number */
175
blockNumber: bigint;
176
/** Gas used */
177
gasUsed: bigint;
178
/** Call status */
179
status: 'success' | 'reverted';
180
/** Event logs */
181
logs: Log[];
182
}
183
```
184
185
### useWaitForCallsStatus
186
187
Hook to wait for batched calls to complete with polling support.
188
189
```typescript { .api }
190
/**
191
* Hook to wait for calls to complete
192
* @param parameters - Wait for calls parameters
193
* @returns Final status when calls complete
194
*/
195
function useWaitForCallsStatus<config = Config, selectData = UseWaitForCallsStatusReturnType>(
196
parameters: UseWaitForCallsStatusParameters<config, selectData>
197
): UseWaitForCallsStatusReturnType<selectData>;
198
199
interface UseWaitForCallsStatusParameters<config = Config, selectData = UseWaitForCallsStatusReturnType> {
200
/** Batch ID to wait for */
201
id: string;
202
/** Chain ID */
203
chainId?: config['chains'][number]['id'];
204
/** Polling interval in milliseconds */
205
pollingInterval?: number;
206
/** Timeout in milliseconds */
207
timeout?: number;
208
config?: Config | config;
209
query?: {
210
enabled?: boolean;
211
gcTime?: number;
212
refetchInterval?: number;
213
retry?: boolean | number;
214
select?: (data: UseWaitForCallsStatusReturnType) => selectData;
215
};
216
}
217
218
type UseWaitForCallsStatusReturnType = UseCallsStatusReturnType;
219
```
220
221
**Usage Example:**
222
223
```typescript
224
import { useSendCalls, useWaitForCallsStatus } from "wagmi";
225
226
function BatchWithStatus() {
227
const { sendCalls, data: batchId } = useSendCalls();
228
229
const {
230
data: status,
231
isLoading,
232
isSuccess,
233
isError
234
} = useWaitForCallsStatus({
235
id: batchId || '',
236
query: { enabled: !!batchId }
237
});
238
239
const handleBatch = () => {
240
sendCalls({
241
calls: [
242
{ to: '0x742d35Cc6634C0532925a3b8D', value: 1000000000000000000n },
243
{ to: '0x8ba1f109551bD432803012645Hac136c', value: 500000000000000000n },
244
],
245
});
246
};
247
248
return (
249
<div>
250
<button onClick={handleBatch}>Send Batch</button>
251
252
{batchId && (
253
<div>
254
<p>Batch ID: {batchId}</p>
255
{isLoading && <p>Waiting for confirmation...</p>}
256
{isSuccess && (
257
<div>
258
<p>Status: {status?.status}</p>
259
<p>Receipts: {status?.receipts?.length || 0}</p>
260
</div>
261
)}
262
{isError && <p>Batch failed</p>}
263
</div>
264
)}
265
</div>
266
);
267
}
268
```
269
270
### useShowCallsStatus
271
272
Hook to show calls status in the wallet UI for user visibility.
273
274
```typescript { .api }
275
/**
276
* Hook to show calls status in wallet UI
277
* @param parameters - Show calls status configuration
278
* @returns Show calls status mutation
279
*/
280
function useShowCallsStatus<config = Config, context = unknown>(
281
parameters?: UseShowCallsStatusParameters<config, context>
282
): UseShowCallsStatusReturnType<config, context>;
283
284
interface UseShowCallsStatusParameters<config = Config, context = unknown> {
285
config?: Config | config;
286
mutation?: {
287
onMutate?: (variables: ShowCallsStatusVariables) => Promise<context> | context;
288
onError?: (error: ShowCallsStatusErrorType, variables: ShowCallsStatusVariables, context?: context) => Promise<void> | void;
289
onSuccess?: (data: ShowCallsStatusData, variables: ShowCallsStatusVariables, context?: context) => Promise<void> | void;
290
onSettled?: (data?: ShowCallsStatusData, error?: ShowCallsStatusErrorType, variables?: ShowCallsStatusVariables, context?: context) => Promise<void> | void;
291
};
292
}
293
294
interface UseShowCallsStatusReturnType<config = Config, context = unknown> {
295
/** Show calls status in wallet */
296
showCallsStatus: (variables: ShowCallsStatusVariables, options?: ShowCallsStatusMutateOptions) => void;
297
/** Async version of showCallsStatus */
298
showCallsStatusAsync: (variables: ShowCallsStatusVariables, options?: ShowCallsStatusMutateAsyncOptions) => Promise<ShowCallsStatusData>;
299
/** Show calls status data */
300
data?: ShowCallsStatusData;
301
/** Show calls status error */
302
error: ShowCallsStatusErrorType | null;
303
/** Show calls status flags */
304
isError: boolean;
305
isIdle: boolean;
306
isPending: boolean;
307
isSuccess: boolean;
308
/** Reset show calls status state */
309
reset: () => void;
310
/** Current status */
311
status: 'error' | 'idle' | 'pending' | 'success';
312
/** Additional variables */
313
variables?: ShowCallsStatusVariables;
314
}
315
316
interface ShowCallsStatusVariables {
317
/** Batch ID to show status for */
318
id: string;
319
}
320
321
type ShowCallsStatusData = boolean; // Whether wallet showed the status
322
```
323
324
### useCapabilities
325
326
Hook to get wallet capabilities for batch transaction support.
327
328
```typescript { .api }
329
/**
330
* Hook to get wallet capabilities
331
* @param parameters - Capabilities query parameters
332
* @returns Available wallet capabilities
333
*/
334
function useCapabilities<config = Config, selectData = UseCapabilitiesReturnType>(
335
parameters?: UseCapabilitiesParameters<config, selectData>
336
): UseCapabilitiesReturnType<selectData>;
337
338
interface UseCapabilitiesParameters<config = Config, selectData = UseCapabilitiesReturnType> {
339
/** Account to get capabilities for */
340
account?: Address;
341
/** Chain ID */
342
chainId?: config['chains'][number]['id'];
343
config?: Config | config;
344
query?: {
345
enabled?: boolean;
346
staleTime?: number;
347
gcTime?: number;
348
select?: (data: UseCapabilitiesReturnType) => selectData;
349
};
350
}
351
352
interface UseCapabilitiesReturnType {
353
[chainId: number]: WalletCapabilities;
354
}
355
356
interface WalletCapabilities {
357
/** Atomic batch transaction support */
358
atomicBatch?: {
359
supported: boolean;
360
};
361
/** Paymaster support */
362
paymasterService?: {
363
supported: boolean;
364
};
365
/** Session key support */
366
sessionKeys?: {
367
supported: boolean;
368
};
369
/** Additional capabilities */
370
[key: string]: unknown;
371
}
372
```
373
374
**Usage Example:**
375
376
```typescript
377
import { useCapabilities, useAccount } from "wagmi";
378
379
function CapabilitiesChecker() {
380
const { address } = useAccount();
381
const { data: capabilities, isLoading } = useCapabilities({
382
account: address,
383
});
384
385
if (isLoading) return <div>Checking capabilities...</div>;
386
387
return (
388
<div>
389
<h3>Wallet Capabilities</h3>
390
{capabilities && Object.entries(capabilities).map(([chainId, caps]) => (
391
<div key={chainId}>
392
<h4>Chain {chainId}</h4>
393
<p>Atomic Batch: {caps.atomicBatch?.supported ? '✅' : '❌'}</p>
394
<p>Paymaster: {caps.paymasterService?.supported ? '✅' : '❌'}</p>
395
<p>Session Keys: {caps.sessionKeys?.supported ? '✅' : '❌'}</p>
396
</div>
397
))}
398
</div>
399
);
400
}
401
```
402
403
### useCall
404
405
Hook to execute a single call (part of the batch transaction system).
406
407
```typescript { .api }
408
/**
409
* Hook to execute a single call
410
* @param parameters - Call execution parameters
411
* @returns Call result
412
*/
413
function useCall<config = Config, selectData = UseCallReturnType>(
414
parameters: UseCallParameters<config, selectData>
415
): UseCallReturnType<selectData>;
416
417
interface UseCallParameters<config = Config, selectData = UseCallReturnType> {
418
/** Target address */
419
to?: Address;
420
/** Call data */
421
data?: Hex;
422
/** Value to send */
423
value?: bigint;
424
/** Account to call from */
425
account?: Address;
426
/** Block number to call at */
427
blockNumber?: bigint;
428
blockTag?: 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized';
429
/** Chain ID */
430
chainId?: config['chains'][number]['id'];
431
/** Gas limit */
432
gas?: bigint;
433
/** Gas price */
434
gasPrice?: bigint;
435
/** Max fee per gas */
436
maxFeePerGas?: bigint;
437
/** Max priority fee per gas */
438
maxPriorityFeePerGas?: bigint;
439
config?: Config | config;
440
query?: {
441
enabled?: boolean;
442
staleTime?: number;
443
select?: (data: UseCallReturnType) => selectData;
444
};
445
}
446
447
type UseCallReturnType = Hex | undefined;
448
```
449
450
## Advanced Batch Transaction Patterns
451
452
### Multi-Token Batch Operations
453
454
```typescript
455
import { useSendCalls, useCapabilities } from "wagmi";
456
import { encodeFunctionData, erc20Abi, parseEther } from "viem";
457
458
function MultiTokenBatch() {
459
const { data: capabilities } = useCapabilities();
460
const { sendCalls, isPending } = useSendCalls();
461
462
const canBatch = capabilities?.[1]?.atomicBatch?.supported;
463
464
const handleComplexBatch = () => {
465
if (!canBatch) {
466
alert('Wallet does not support atomic batch transactions');
467
return;
468
}
469
470
// Create multiple token operations
471
const approveUSDC = encodeFunctionData({
472
abi: erc20Abi,
473
functionName: 'approve',
474
args: ['0x7f39C581F595B53c5cb19bD0b3f8DA6c935E2Ca0', parseEther('1000')],
475
});
476
477
const transferDAI = encodeFunctionData({
478
abi: erc20Abi,
479
functionName: 'transfer',
480
args: ['0x742d35Cc6634C0532925a3b8D', parseEther('500')],
481
});
482
483
const transferUSDC = encodeFunctionData({
484
abi: erc20Abi,
485
functionName: 'transfer',
486
args: ['0x8ba1f109551bD432803012645Hac136c', 1000000000n], // 1000 USDC
487
});
488
489
sendCalls({
490
calls: [
491
{
492
to: '0xA0b86a33E6417C90CC5F6d2c4a29f9D7e5D8ecf0', // USDC
493
data: approveUSDC,
494
},
495
{
496
to: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
497
data: transferDAI,
498
},
499
{
500
to: '0xA0b86a33E6417C90CC5F6d2c4a29f9D7e5D8ecf0', // USDC
501
data: transferUSDC,
502
},
503
],
504
});
505
};
506
507
return (
508
<div>
509
<p>Batch Support: {canBatch ? '✅' : '❌'}</p>
510
<button
511
onClick={handleComplexBatch}
512
disabled={!canBatch || isPending}
513
>
514
{isPending ? 'Processing...' : 'Execute Multi-Token Batch'}
515
</button>
516
</div>
517
);
518
}
519
```
520
521
### Batch Status Monitor
522
523
```typescript
524
import {
525
useSendCalls,
526
useCallsStatus,
527
useShowCallsStatus
528
} from "wagmi";
529
import { useState } from "react";
530
531
function BatchStatusMonitor() {
532
const [batchIds, setBatchIds] = useState<string[]>([]);
533
534
const { sendCalls } = useSendCalls({
535
mutation: {
536
onSuccess(data) {
537
setBatchIds(prev => [...prev, data.id]);
538
},
539
},
540
});
541
542
const { showCallsStatus } = useShowCallsStatus();
543
544
return (
545
<div>
546
<h3>Batch Status Monitor</h3>
547
548
<button onClick={() => sendCalls({
549
calls: [
550
{ to: '0x742d35Cc6634C0532925a3b8D', value: parseEther('0.01') }
551
]
552
})}>
553
Send New Batch
554
</button>
555
556
<div>
557
<h4>Active Batches ({batchIds.length})</h4>
558
{batchIds.map(id => (
559
<BatchStatusItem
560
key={id}
561
batchId={id}
562
onShowStatus={() => showCallsStatus({ id })}
563
/>
564
))}
565
</div>
566
</div>
567
);
568
}
569
570
function BatchStatusItem({
571
batchId,
572
onShowStatus
573
}: {
574
batchId: string;
575
onShowStatus: () => void;
576
}) {
577
const { data: status, isLoading } = useCallsStatus({ id: batchId });
578
579
return (
580
<div style={{ border: '1px solid #ccc', padding: '8px', margin: '4px' }}>
581
<p>ID: {batchId}</p>
582
<p>Status: {isLoading ? 'Loading...' : status?.status}</p>
583
<p>Receipts: {status?.receipts?.length || 0}</p>
584
<button onClick={onShowStatus}>Show in Wallet</button>
585
</div>
586
);
587
}
588
```
589
590
## Common Types
591
592
```typescript { .api }
593
type Address = `0x${string}`;
594
type Hash = `0x${string}`;
595
type Hex = `0x${string}`;
596
597
interface Log {
598
address: Address;
599
topics: readonly Hash[];
600
data: Hex;
601
blockHash?: Hash;
602
blockNumber?: bigint;
603
transactionHash?: Hash;
604
transactionIndex?: number;
605
logIndex?: number;
606
removed?: boolean;
607
}
608
609
interface SendCallsMutateOptions {
610
onError?: (error: Error, variables: SendCallsVariables, context?: unknown) => void;
611
onSuccess?: (data: SendCallsData, variables: SendCallsVariables, context?: unknown) => void;
612
onSettled?: (data?: SendCallsData, error?: Error, variables?: SendCallsVariables, context?: unknown) => void;
613
}
614
615
interface ShowCallsStatusMutateOptions {
616
onError?: (error: Error, variables: ShowCallsStatusVariables, context?: unknown) => void;
617
onSuccess?: (data: boolean, variables: ShowCallsStatusVariables, context?: unknown) => void;
618
onSettled?: (data?: boolean, error?: Error, variables?: ShowCallsStatusVariables, context?: unknown) => void;
619
}
620
621
type SendCallsErrorType = Error;
622
type ShowCallsStatusErrorType = Error;
623
624
interface BatchTransactionSummary {
625
id: string;
626
status: 'PENDING' | 'CONFIRMED' | 'FAILED';
627
callCount: number;
628
successCount: number;
629
failureCount: number;
630
totalGasUsed?: bigint;
631
blockNumber?: bigint;
632
}
633
```