@formo/analytics 1.36.0 → 1.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,123 @@
1
+ import { TransactionStatus } from "../types/events";
2
+ /**
3
+ * The batch identifier from a `wallet_sendCalls` result.
4
+ *
5
+ * EIP-5792 settled on `{ id }`, but wallets shipped against the earlier
6
+ * draft return a bare string. Both are accepted so a wallet on either
7
+ * version is still grouped.
8
+ */
9
+ export function readBatchId(result) {
10
+ if (typeof result === "string" && result.length > 0)
11
+ return result;
12
+ if (result && typeof result === "object") {
13
+ var id = result.id;
14
+ if (typeof id === "string" && id.length > 0)
15
+ return id;
16
+ }
17
+ return undefined;
18
+ }
19
+ /**
20
+ * The numeric EIP-5792 status code from a settlement result.
21
+ *
22
+ * A wallet answers `wallet_getCallsStatus` with a numeric `status`; viem's
23
+ * `getCallsStatus` renames that to `statusCode` and puts a summary string in
24
+ * `status` instead. Both shapes arrive here depending on the capture path,
25
+ * so read the number wherever it is and never trust the string.
26
+ */
27
+ export function readBatchStatusCode(res) {
28
+ if (typeof (res === null || res === void 0 ? void 0 : res.statusCode) === "number")
29
+ return res.statusCode;
30
+ if (typeof (res === null || res === void 0 ? void 0 : res.status) === "number")
31
+ return res.status;
32
+ return undefined;
33
+ }
34
+ /**
35
+ * The chain a settled batch reports itself on.
36
+ *
37
+ * EIP-5792 v2 puts `chainId` in the `wallet_getCallsStatus` response as hex;
38
+ * viem returns it as a number. Either way it names the chain the batch
39
+ * actually settled on, which outranks a chain merely inferred from the
40
+ * connection at broadcast time - the wallet can move chains while the
41
+ * prompt is up.
42
+ */
43
+ export function readBatchChainId(res) {
44
+ var raw = res === null || res === void 0 ? void 0 : res.chainId;
45
+ if (typeof raw === "number" && Number.isFinite(raw) && raw > 0)
46
+ return raw;
47
+ if (typeof raw === "string") {
48
+ var parsed = parseInt(raw, 16);
49
+ if (Number.isFinite(parsed) && parsed > 0)
50
+ return parsed;
51
+ }
52
+ return undefined;
53
+ }
54
+ /**
55
+ * How one call in a settled batch ended.
56
+ *
57
+ * A per-call receipt is authoritative where it exists: that is what makes a
58
+ * partially reverted non-atomic batch report honestly rather than tarring
59
+ * every call with the batch's worst outcome. A receipt whose own status is
60
+ * unreadable falls back to the batch verdict rather than being assumed good.
61
+ *
62
+ * Receipt statuses come in two spellings: raw RPC (`"0x0"`/`"0x1"`, or the
63
+ * numbers) and viem-formatted (`"reverted"`/`"success"`), because the wagmi
64
+ * path sees receipts after viem has normalised them.
65
+ *
66
+ * The codes are EIP-5792's: 200 confirmed, 400 failed BEFORE landing on
67
+ * chain, 500 reverted, 600 partially reverted. 400 is a rejection, not a
68
+ * revert - nothing was mined, so calling it reverted would misreport gas
69
+ * spent and on-chain activity that never happened.
70
+ *
71
+ * Returns undefined when the call cannot be decided, which happens on 600
72
+ * for a call the wallet gave no receipt for.
73
+ */
74
+ export function batchCallOutcome(code, receipt) {
75
+ var receiptStatus = receipt === null || receipt === void 0 ? void 0 : receipt.status;
76
+ if (receiptStatus !== undefined) {
77
+ return receiptStatus === "0x0" ||
78
+ receiptStatus === 0 ||
79
+ receiptStatus === "reverted"
80
+ ? TransactionStatus.REVERTED
81
+ : TransactionStatus.CONFIRMED;
82
+ }
83
+ if (code >= 600)
84
+ return undefined;
85
+ if (code >= 500)
86
+ return TransactionStatus.REVERTED;
87
+ if (code >= 400)
88
+ return TransactionStatus.REJECTED;
89
+ return TransactionStatus.CONFIRMED;
90
+ }
91
+ /**
92
+ * The receipt that decides call `index`, honouring atomic execution.
93
+ *
94
+ * An atomic batch lands as ONE on-chain transaction, so the wallet returns a
95
+ * single receipt covering every call. Indexing receipts positionally there
96
+ * would hand the shared hash to call 0 and leave its siblings hashless and
97
+ * decided only by the batch verdict. Every call in an atomic batch shares
98
+ * the one receipt - same hash, same fate - which is also what makes
99
+ * `count(distinct transaction_hash)` count on-chain transactions correctly.
100
+ *
101
+ * The wallet's own `atomic` flag is authoritative in BOTH directions. An
102
+ * explicit `atomic: false` with a single receipt is a real shape - a
103
+ * non-atomic batch whose execution stopped after one call mined - and
104
+ * sharing that receipt would hand calls that never reached the chain a
105
+ * transaction hash they do not have. Only when the field is ABSENT (a
106
+ * wallet predating it, reached over raw EIP-1193; viem fills the field in,
107
+ * so the wagmi path never lands here) does the conservative inference
108
+ * apply: one receipt for several calls on a batch that is NOT partially
109
+ * reverted can only be atomic execution (600 explicitly means some calls
110
+ * reverted and others did not, which one shared transaction cannot do).
111
+ */
112
+ export function batchReceiptForCall(res, index, callCount) {
113
+ var _a;
114
+ var receipts = Array.isArray(res === null || res === void 0 ? void 0 : res.receipts) ? res.receipts : [];
115
+ var code = (_a = readBatchStatusCode(res)) !== null && _a !== void 0 ? _a : 0;
116
+ var atomic = (res === null || res === void 0 ? void 0 : res.atomic) === true ||
117
+ ((res === null || res === void 0 ? void 0 : res.atomic) === undefined &&
118
+ receipts.length === 1 &&
119
+ callCount > 1 &&
120
+ code < 600);
121
+ return atomic ? receipts[0] : receipts[index];
122
+ }
123
+ //# sourceMappingURL=batch.js.map
@@ -1,2 +1,2 @@
1
- export declare const version = "1.36.0";
1
+ export declare const version = "1.37.0";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,4 +1,4 @@
1
1
  // This file is auto-generated by scripts/update-version.js during npm version
2
2
  // Do not edit manually - it will be overwritten
3
- export var version = '1.36.0';
3
+ export var version = '1.37.0';
4
4
  //# sourceMappingURL=version.js.map
@@ -96,6 +96,8 @@ export declare class WagmiEventHandler {
96
96
  * broadcast to match the receipt against.
97
97
  */
98
98
  private get pendingTransactions();
99
+ /** Broadcast batches awaiting `callsStatus`, shared like the map above. */
100
+ private get pendingBatches();
99
101
  constructor(formoAnalytics: FormoAnalytics, wagmiConfig: WagmiConfig, queryClient?: QueryClient);
100
102
  /**
101
103
  * Set up listeners for wallet connection, disconnection, and chain changes
@@ -228,6 +230,30 @@ export declare class WagmiEventHandler {
228
230
  * Handle query cache events (transaction confirmations)
229
231
  */
230
232
  private handleQueryEvent;
233
+ /**
234
+ * Settle a just-registered batch from a status query that already ran.
235
+ *
236
+ * Best-effort by design: the minimal QueryClient interface the SDK
237
+ * accepts is not guaranteed to expose cache lookup, and a missing
238
+ * `getAll` just means settlement waits for the next query event, which
239
+ * is where it normally comes from anyway.
240
+ */
241
+ private settleFromCachedCallsStatus;
242
+ /**
243
+ * Settle an EIP-5792 batch from a `callsStatus` query.
244
+ *
245
+ * Only batches whose broadcast this SDK observed are settled: the batch id
246
+ * must be in `pendingBatches`, for the same reason receipt queries are
247
+ * gated on an observed hash - queries are visible to any code sharing the
248
+ * QueryClient, and emitting for an id we never saw broadcast would let a
249
+ * forged query invent transactions.
250
+ *
251
+ * Outcome semantics are shared with the EIP-1193 path (`src/evm/batch.ts`):
252
+ * per-call receipts outrank the batch verdict, an atomic batch's single
253
+ * receipt reaches every call, and a 600 leaves receipt-less calls
254
+ * unsettled rather than guessed.
255
+ */
256
+ private handleCallsStatusQuery;
231
257
  /**
232
258
  * Handle waitForTransactionReceipt query completion
233
259
  * Emits CONFIRMED or REVERTED transaction status
@@ -245,6 +271,23 @@ export declare class WagmiEventHandler {
245
271
  * Handle transaction mutations (sendTransaction, writeContract)
246
272
  */
247
273
  private handleTransactionMutation;
274
+ /**
275
+ * One `transaction` event per call in an EIP-5792 batch, wagmi path.
276
+ *
277
+ * Mirrors `EvmRequestTracker.trackBatchedCalls` exactly: the CALL is the
278
+ * unit of attribution, so each call gets its own STARTED at pending and
279
+ * BROADCASTED (with `batch_id`) when the wallet returns an id. The batch's
280
+ * on-chain outcome arrives through the `callsStatus` query, handled in
281
+ * `handleCallsStatusQuery`.
282
+ *
283
+ * Rejection matches the 1193 path's rule: only a user rejection (4001
284
+ * anywhere in the error chain) marks the calls rejected - one dismissal
285
+ * dismisses the whole prompt, so every call in it is rejected, and
286
+ * reporting only the first would undercount. Any other error (a wallet
287
+ * without EIP-5792 support, a transport failure) emits nothing further:
288
+ * inventing a rejection the user never made would be worse.
289
+ */
290
+ private handleSendCallsMutation;
248
291
  /**
249
292
  * Get the current Wagmi state
250
293
  * Supports both getState() method and direct state property access
@@ -54,6 +54,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
54
54
  };
55
55
  import { SignatureStatus, TransactionStatus } from "../types/events";
56
56
  import { logger } from "../logger";
57
+ import { readBatchId, readBatchStatusCode, readBatchChainId, batchCallOutcome, batchReceiptForCall, } from "../evm/batch";
57
58
  import { encodeWriteContractData, concatCalldataWithSuffix, extractFunctionArgs, buildSafeFunctionArgs, } from "./utils";
58
59
  /**
59
60
  * Built-in transaction fields that could collide with function args.
@@ -196,6 +197,25 @@ var ownerKey = function (writeKey, config) {
196
197
  }
197
198
  return "".concat(writeKey, ":").concat(id);
198
199
  };
200
+ /**
201
+ * Was this mutation error the user dismissing the wallet prompt?
202
+ *
203
+ * Matches the EIP-1193 path's rule (code 4001), but a wagmi mutation error
204
+ * arrives wrapped: viem nests the RPC error under `cause`, sometimes twice.
205
+ * Walk the chain rather than trusting the top level, and accept viem's
206
+ * `UserRejectedRequestError` by name for wallets that map the rejection to a
207
+ * typed error without preserving the numeric code.
208
+ */
209
+ function isUserRejection(error) {
210
+ var cursor = error;
211
+ for (var depth = 0; cursor && depth < 5; depth++) {
212
+ if (cursor.code === 4001 || cursor.name === "UserRejectedRequestError") {
213
+ return true;
214
+ }
215
+ cursor = cursor.cause;
216
+ }
217
+ return false;
218
+ }
199
219
  /**
200
220
  * Pending transactions, shared per destination rather than per handler.
201
221
  *
@@ -205,6 +225,7 @@ var ownerKey = function (writeKey, config) {
205
225
  * broadcast to match the receipt against.
206
226
  */
207
227
  var pendingTransactionsByDestination = new Map();
228
+ var pendingBatchesByDestination = new Map();
208
229
  /**
209
230
  * Pending records outlive a rebuild by the same grace period as the markers.
210
231
  * The ordinary rebuild is cleanup THEN remount, so dropping them the instant
@@ -219,6 +240,7 @@ function schedulePendingTransactionExpiry(key) {
219
240
  var timer = setTimeout(function () {
220
241
  pendingTransactionExpiry.delete(key);
221
242
  pendingTransactionsByDestination.delete(key);
243
+ pendingBatchesByDestination.delete(key);
222
244
  }, MARKER_GRACE_MS);
223
245
  (_b = (_a = timer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
224
246
  pendingTransactionExpiry.set(key, timer);
@@ -285,6 +307,7 @@ export function __resetSeededWallet() {
285
307
  pendingTransactionExpiry.forEach(function (t) { return clearTimeout(t); });
286
308
  pendingTransactionExpiry.clear();
287
309
  pendingTransactionsByDestination.clear();
310
+ pendingBatchesByDestination.clear();
288
311
  announcedConnections.clear();
289
312
  liveHandlers.clear();
290
313
  markerExpiry.forEach(function (timer) { return clearTimeout(timer); });
@@ -497,6 +520,21 @@ var WagmiEventHandler = /** @class */ (function () {
497
520
  enumerable: false,
498
521
  configurable: true
499
522
  });
523
+ Object.defineProperty(WagmiEventHandler.prototype, "pendingBatches", {
524
+ /** Broadcast batches awaiting `callsStatus`, shared like the map above. */
525
+ get: function () {
526
+ var _a;
527
+ var key = (_a = this.ownerKey) !== null && _a !== void 0 ? _a : "";
528
+ var map = pendingBatchesByDestination.get(key);
529
+ if (!map) {
530
+ map = new Map();
531
+ pendingBatchesByDestination.set(key, map);
532
+ }
533
+ return map;
534
+ },
535
+ enumerable: false,
536
+ configurable: true
537
+ });
500
538
  /**
501
539
  * Set up listeners for wallet connection, disconnection, and chain changes
502
540
  */
@@ -1449,8 +1487,23 @@ var WagmiEventHandler = /** @class */ (function () {
1449
1487
  return;
1450
1488
  }
1451
1489
  var queryType = queryKey[0];
1452
- // Only handle waitForTransactionReceipt queries
1453
- if (queryType !== "waitForTransactionReceipt") {
1490
+ // Only the two query families that settle something we broadcast:
1491
+ // waitForTransactionReceipt for single transactions, callsStatus for
1492
+ // EIP-5792 batches (both useCallsStatus and useWaitForCallsStatus share
1493
+ // the 'callsStatus' key, in wagmi 2 and 3 alike).
1494
+ if (queryType !== "waitForTransactionReceipt" && queryType !== "callsStatus") {
1495
+ return;
1496
+ }
1497
+ // Batch settlement dedupes on the pending-batch registry, NOT on
1498
+ // processedQueries: settling deletes the registration, so a duplicate
1499
+ // delivery finds nothing to do. A processed-key here would be worse
1500
+ // than redundant - the status query can complete BEFORE the sendCalls
1501
+ // mutation registers the batch (TanStack dispatches a mutation's
1502
+ // success state after its onSuccess callbacks, and apps await the
1503
+ // status inside onSuccess), and a key recorded on that early skip
1504
+ // would block every refetch from ever settling the batch.
1505
+ if (queryType === "callsStatus") {
1506
+ this.handleCallsStatusQuery(query);
1454
1507
  return;
1455
1508
  }
1456
1509
  var state = query.state;
@@ -1483,6 +1536,111 @@ var WagmiEventHandler = /** @class */ (function () {
1483
1536
  // Clean up old processed queries to prevent memory leaks
1484
1537
  cleanupOldEntries(this.processedQueries);
1485
1538
  };
1539
+ /**
1540
+ * Settle a just-registered batch from a status query that already ran.
1541
+ *
1542
+ * Best-effort by design: the minimal QueryClient interface the SDK
1543
+ * accepts is not guaranteed to expose cache lookup, and a missing
1544
+ * `getAll` just means settlement waits for the next query event, which
1545
+ * is where it normally comes from anyway.
1546
+ */
1547
+ WagmiEventHandler.prototype.settleFromCachedCallsStatus = function (batchId) {
1548
+ var _a, _b, _c;
1549
+ try {
1550
+ var cache = (_a = this.queryClient) === null || _a === void 0 ? void 0 : _a.getQueryCache();
1551
+ var queries = (_b = cache === null || cache === void 0 ? void 0 : cache.getAll) === null || _b === void 0 ? void 0 : _b.call(cache);
1552
+ if (!Array.isArray(queries))
1553
+ return;
1554
+ for (var _i = 0, queries_1 = queries; _i < queries_1.length; _i++) {
1555
+ var query = queries_1[_i];
1556
+ var key = query === null || query === void 0 ? void 0 : query.queryKey;
1557
+ if (Array.isArray(key) &&
1558
+ key[0] === "callsStatus" &&
1559
+ ((_c = key[1]) === null || _c === void 0 ? void 0 : _c.id) === batchId) {
1560
+ this.handleCallsStatusQuery(query);
1561
+ }
1562
+ }
1563
+ }
1564
+ catch (error) {
1565
+ logger.debug("WagmiEventHandler: cached callsStatus scan failed", error);
1566
+ }
1567
+ };
1568
+ /**
1569
+ * Settle an EIP-5792 batch from a `callsStatus` query.
1570
+ *
1571
+ * Only batches whose broadcast this SDK observed are settled: the batch id
1572
+ * must be in `pendingBatches`, for the same reason receipt queries are
1573
+ * gated on an observed hash - queries are visible to any code sharing the
1574
+ * QueryClient, and emitting for an id we never saw broadcast would let a
1575
+ * forged query invent transactions.
1576
+ *
1577
+ * Outcome semantics are shared with the EIP-1193 path (`src/evm/batch.ts`):
1578
+ * per-call receipts outrank the batch verdict, an atomic batch's single
1579
+ * receipt reaches every call, and a 600 leaves receipt-less calls
1580
+ * unsettled rather than guessed.
1581
+ */
1582
+ WagmiEventHandler.prototype.handleCallsStatusQuery = function (query) {
1583
+ var _this = this;
1584
+ var _a;
1585
+ if (!this.formo.isAutocaptureEnabled("transaction")) {
1586
+ return;
1587
+ }
1588
+ var queryKey = query.queryKey;
1589
+ // Query key format: ['callsStatus', { id, ... }]
1590
+ var params = queryKey[1];
1591
+ var batchId = params === null || params === void 0 ? void 0 : params.id;
1592
+ if (!batchId) {
1593
+ return;
1594
+ }
1595
+ var pending = this.pendingBatches.get(batchId);
1596
+ if (!pending) {
1597
+ logger.debug("WagmiEventHandler: unobserved batch", { batchId: batchId });
1598
+ return;
1599
+ }
1600
+ var state = query.state;
1601
+ if (state.status !== "success" || !state.data) {
1602
+ return;
1603
+ }
1604
+ try {
1605
+ var res_1 = state.data;
1606
+ var code_1 = readBatchStatusCode(res_1);
1607
+ // Below 200 the batch is still pending; the query will update again.
1608
+ if (code_1 === undefined || code_1 < 200) {
1609
+ return;
1610
+ }
1611
+ logger.debug("WagmiEventHandler: batch settled", { batchId: batchId, code: code_1 });
1612
+ // An explicit mutation chain is authoritative. Otherwise prefer the
1613
+ // chain the settlement result names - EIP-5792 v2 reports where the
1614
+ // batch actually landed - over one inferred from the connection at
1615
+ // broadcast, which goes stale if the wallet moves chains while the
1616
+ // prompt is up. Same precedence as the single-transaction receipt
1617
+ // path.
1618
+ var settledChainId_1 = pending.chainIdWasExplicit
1619
+ ? pending.chainId
1620
+ : (_a = readBatchChainId(res_1)) !== null && _a !== void 0 ? _a : pending.chainId;
1621
+ pending.calls.forEach(function (call, index) {
1622
+ var receipt = batchReceiptForCall(res_1, index, pending.calls.length);
1623
+ var outcome = batchCallOutcome(code_1, receipt);
1624
+ // 600 means SOME calls reverted, so a call with no receipt of its
1625
+ // own has not been decided. Reporting it either way would invent a
1626
+ // result; leaving it unsettled is the honest answer.
1627
+ if (outcome === undefined)
1628
+ return;
1629
+ _this.formo.transaction(__assign(__assign(__assign(__assign({ status: outcome, chainId: settledChainId_1 || 0, address: pending.address }, (call.data && { data: call.data })), (call.to && { to: call.to })), (call.value && { value: call.value })), ((receipt === null || receipt === void 0 ? void 0 : receipt.transactionHash)
1630
+ ? { transactionHash: receipt.transactionHash }
1631
+ : {})), {
1632
+ batch_size: pending.calls.length,
1633
+ batch_index: index,
1634
+ batch_id: batchId,
1635
+ });
1636
+ });
1637
+ // Settled; a later refetch of the same query must not re-emit.
1638
+ this.pendingBatches.delete(batchId);
1639
+ }
1640
+ catch (error) {
1641
+ logger.error("WagmiEventHandler: callsStatus error:", error);
1642
+ }
1643
+ };
1486
1644
  /**
1487
1645
  * Handle waitForTransactionReceipt query completion
1488
1646
  * Emits CONFIRMED or REVERTED transaction status
@@ -1612,6 +1770,13 @@ var WagmiEventHandler = /** @class */ (function () {
1612
1770
  if (mutationType === "sendTransaction" || mutationType === "writeContract") {
1613
1771
  this.handleTransactionMutation(mutationType, mutation);
1614
1772
  }
1773
+ // Handle EIP-5792 batch mutations (useSendCalls). Absent this branch,
1774
+ // wagmi-mode apps captured nothing for a batch: the EIP-1193 request
1775
+ // wrapper that handles `wallet_sendCalls` is never installed in wagmi
1776
+ // mode, so the mutation was the only place the batch was visible at all.
1777
+ if (mutationType === "sendCalls") {
1778
+ this.handleSendCallsMutation(mutation);
1779
+ }
1615
1780
  // Clean up old processed mutations to prevent memory leaks
1616
1781
  cleanupOldEntries(this.processedMutations);
1617
1782
  };
@@ -1801,6 +1966,92 @@ var WagmiEventHandler = /** @class */ (function () {
1801
1966
  logger.error("WagmiEventHandler: Error handling transaction mutation:", error);
1802
1967
  }
1803
1968
  };
1969
+ /**
1970
+ * One `transaction` event per call in an EIP-5792 batch, wagmi path.
1971
+ *
1972
+ * Mirrors `EvmRequestTracker.trackBatchedCalls` exactly: the CALL is the
1973
+ * unit of attribution, so each call gets its own STARTED at pending and
1974
+ * BROADCASTED (with `batch_id`) when the wallet returns an id. The batch's
1975
+ * on-chain outcome arrives through the `callsStatus` query, handled in
1976
+ * `handleCallsStatusQuery`.
1977
+ *
1978
+ * Rejection matches the 1193 path's rule: only a user rejection (4001
1979
+ * anywhere in the error chain) marks the calls rejected - one dismissal
1980
+ * dismisses the whole prompt, so every call in it is rejected, and
1981
+ * reporting only the first would undercount. Any other error (a wallet
1982
+ * without EIP-5792 support, a transport failure) emits nothing further:
1983
+ * inventing a rejection the user never made would be worse.
1984
+ */
1985
+ WagmiEventHandler.prototype.handleSendCallsMutation = function (mutation) {
1986
+ var _this = this;
1987
+ if (!this.formo.isAutocaptureEnabled("transaction")) {
1988
+ return;
1989
+ }
1990
+ var state = mutation.state;
1991
+ var variables = state.variables || {};
1992
+ var rawCalls = Array.isArray(variables.calls) ? variables.calls : [];
1993
+ if (rawCalls.length === 0) {
1994
+ return;
1995
+ }
1996
+ // Same resolution order as single transactions: an explicit per-call
1997
+ // value beats the tracked connection.
1998
+ var explicitChainId = normalizeChainId(variables.chainId);
1999
+ var chainId = explicitChainId !== null && explicitChainId !== void 0 ? explicitChainId : this.trackingState.lastChainId;
2000
+ var accountAddress = resolveAccountAddress(variables.account);
2001
+ var userAddress = accountAddress || this.trackingState.lastAddress;
2002
+ if (!userAddress) {
2003
+ logger.warn("WagmiEventHandler: sendCalls without address");
2004
+ return;
2005
+ }
2006
+ try {
2007
+ var calls_1 = rawCalls.map(function (call) { return ({
2008
+ to: call === null || call === void 0 ? void 0 : call.to,
2009
+ value: (call === null || call === void 0 ? void 0 : call.value) !== undefined ? String(call.value) : undefined,
2010
+ data: call === null || call === void 0 ? void 0 : call.data,
2011
+ }); });
2012
+ var emitAll = function (status, extra) {
2013
+ calls_1.forEach(function (call, index) {
2014
+ _this.formo.transaction(__assign(__assign(__assign({ status: status, chainId: chainId || 0, address: userAddress }, (call.data && { data: call.data })), (call.to && { to: call.to })), (call.value && { value: call.value })), __assign({ batch_size: calls_1.length, batch_index: index }, extra));
2015
+ });
2016
+ };
2017
+ if (state.status === "pending") {
2018
+ // STARTED carries no batch id, exactly as a single transaction has
2019
+ // no hash yet: the wallet has not issued one.
2020
+ logger.debug("WagmiEventHandler: sendCalls start", { calls: calls_1.length });
2021
+ emitAll(TransactionStatus.STARTED);
2022
+ }
2023
+ else if (state.status === "success") {
2024
+ var batchId = readBatchId(state.data);
2025
+ logger.debug("WagmiEventHandler: sendCalls broadcast", { batchId: batchId });
2026
+ emitAll(TransactionStatus.BROADCASTED, batchId ? { batch_id: batchId } : undefined);
2027
+ if (batchId) {
2028
+ this.pendingBatches.set(batchId, __assign(__assign({ address: userAddress }, (chainId !== undefined && { chainId: chainId })), { chainIdWasExplicit: explicitChainId !== undefined, calls: calls_1 }));
2029
+ // Same bound as pendingTransactions, same reason.
2030
+ if (this.pendingBatches.size > 100) {
2031
+ var keys = Array.from(this.pendingBatches.keys());
2032
+ for (var i = 0; i < 50 && i < keys.length; i++) {
2033
+ this.pendingBatches.delete(keys[i]);
2034
+ }
2035
+ }
2036
+ // The status query can have completed BEFORE this registration:
2037
+ // TanStack dispatches a mutation's success state after its
2038
+ // onSuccess callbacks, and apps await waitForCallsStatus inside
2039
+ // onSuccess. That early query event found no registration and did
2040
+ // nothing, so look for its settled result in the cache now.
2041
+ this.settleFromCachedCallsStatus(batchId);
2042
+ }
2043
+ }
2044
+ else if (state.status === "error") {
2045
+ if (isUserRejection(state.error)) {
2046
+ logger.debug("WagmiEventHandler: sendCalls rejected");
2047
+ emitAll(TransactionStatus.REJECTED);
2048
+ }
2049
+ }
2050
+ }
2051
+ catch (error) {
2052
+ logger.error("WagmiEventHandler: sendCalls error:", error);
2053
+ }
2054
+ };
1804
2055
  /**
1805
2056
  * Get the current Wagmi state
1806
2057
  * Supports both getState() method and direct state property access