@formo/analytics 1.38.0 → 1.38.2

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.
Files changed (34) hide show
  1. package/dist/cjs/src/FormoAnalytics.d.ts +15 -4
  2. package/dist/cjs/src/FormoAnalytics.js +37 -6
  3. package/dist/cjs/src/FormoAnalyticsProvider.d.ts +8 -0
  4. package/dist/cjs/src/FormoAnalyticsProvider.js +41 -32
  5. package/dist/cjs/src/evm/EvmEventTracker.d.ts +100 -9
  6. package/dist/cjs/src/evm/EvmEventTracker.js +357 -19
  7. package/dist/cjs/src/evm/EvmProviderRegistry.d.ts +34 -2
  8. package/dist/cjs/src/evm/EvmProviderRegistry.js +61 -4
  9. package/dist/cjs/src/evm/EvmRequestTracker.d.ts +21 -4
  10. package/dist/cjs/src/evm/EvmRequestTracker.js +54 -28
  11. package/dist/cjs/src/version.d.ts +1 -1
  12. package/dist/cjs/src/version.js +1 -1
  13. package/dist/cjs/src/wagmi/WagmiEventHandler.d.ts +67 -1
  14. package/dist/cjs/src/wagmi/WagmiEventHandler.js +286 -39
  15. package/dist/cjs/src/wagmi/types.d.ts +6 -0
  16. package/dist/cjs/src/wagmi/utils.js +9 -1
  17. package/dist/esm/src/FormoAnalytics.d.ts +15 -4
  18. package/dist/esm/src/FormoAnalytics.js +37 -6
  19. package/dist/esm/src/FormoAnalyticsProvider.d.ts +8 -0
  20. package/dist/esm/src/FormoAnalyticsProvider.js +39 -31
  21. package/dist/esm/src/evm/EvmEventTracker.d.ts +100 -9
  22. package/dist/esm/src/evm/EvmEventTracker.js +357 -19
  23. package/dist/esm/src/evm/EvmProviderRegistry.d.ts +34 -2
  24. package/dist/esm/src/evm/EvmProviderRegistry.js +61 -4
  25. package/dist/esm/src/evm/EvmRequestTracker.d.ts +21 -4
  26. package/dist/esm/src/evm/EvmRequestTracker.js +54 -28
  27. package/dist/esm/src/version.d.ts +1 -1
  28. package/dist/esm/src/version.js +1 -1
  29. package/dist/esm/src/wagmi/WagmiEventHandler.d.ts +67 -1
  30. package/dist/esm/src/wagmi/WagmiEventHandler.js +286 -39
  31. package/dist/esm/src/wagmi/types.d.ts +6 -0
  32. package/dist/esm/src/wagmi/utils.js +9 -1
  33. package/dist/index.umd.min.js +1 -1
  34. package/package.json +2 -2
@@ -45,6 +45,24 @@ export declare class EvmProviderRegistry {
45
45
  private listeners;
46
46
  /** The window-injected provider, once detected, so it is not re-wrapped. */
47
47
  private injectedDetail?;
48
+ /**
49
+ * Attribution supplied by the integration layer for a provider that was
50
+ * never announced: the wagmi fallback wrap names a connector's provider
51
+ * after the CONNECTOR, so request-derived events carry the same wallet
52
+ * name as the hook-driven events from the same connection. Without it
53
+ * the name came from flag sniffing, and a custom or embedded connector
54
+ * whose provider exposes no recognised flag split one wallet's activity
55
+ * between "Injected Provider" and the connector's name.
56
+ *
57
+ * A RESOLVER, read at each `infoFor`, not a value: the name is live for
58
+ * the connector the integration layer bound it to (a WalletConnect
59
+ * session that resolves or changes its peer renames without a re-wrap),
60
+ * and the integration layer names events on its hook path with the same
61
+ * function, so the two paths cannot disagree. Which connector a
62
+ * provider is bound to is the integration layer's decision; it is not
63
+ * necessarily the connector that is current when the request runs.
64
+ */
65
+ private attributions;
48
66
  constructor(deps: EvmProviderRegistryDeps);
49
67
  get all(): readonly EIP6963ProviderDetail[];
50
68
  isTracked(provider: EIP1193Provider): boolean;
@@ -62,11 +80,25 @@ export declare class EvmProviderRegistry {
62
80
  };
63
81
  /** Add a discovered provider once. Returns false if already present. */
64
82
  add(detail: EIP6963ProviderDetail): boolean;
83
+ /**
84
+ * Record (or, with `undefined`, forget) the integration layer's own
85
+ * attribution resolver for a provider. See `attributions`.
86
+ */
87
+ rememberAttribution(provider: EIP1193Provider | undefined, resolve: (() => {
88
+ name: string;
89
+ rdns?: string;
90
+ } | undefined) | undefined): void;
91
+ /** The supplied attribution for a provider, if any resolves right now. */
92
+ private suppliedAttributionFor;
65
93
  /**
66
94
  * A provider's display name and rdns.
67
95
  *
68
- * EIP-6963 metadata is authoritative when we have it; otherwise fall back to
69
- * sniffing the injected provider, which is all a pre-6963 wallet offers.
96
+ * EIP-6963 metadata is authoritative when we have it. A supplied
97
+ * attribution (the connector a wagmi app connected through) comes next:
98
+ * it describes the SESSION, which is what the hook-driven events report.
99
+ * Otherwise fall back to sniffing the injected provider, which is all a
100
+ * pre-6963 wallet offers; a supplied name without an rdns keeps the
101
+ * sniffed rdns.
70
102
  */
71
103
  infoFor(provider: EIP1193Provider): {
72
104
  name: string;
@@ -74,6 +74,24 @@ var EvmProviderRegistry = /** @class */ (function () {
74
74
  this.chainGenerations = new WeakMap();
75
75
  /** Listeners this SDK attached, so teardown can remove exactly those. */
76
76
  this.listeners = new Map();
77
+ /**
78
+ * Attribution supplied by the integration layer for a provider that was
79
+ * never announced: the wagmi fallback wrap names a connector's provider
80
+ * after the CONNECTOR, so request-derived events carry the same wallet
81
+ * name as the hook-driven events from the same connection. Without it
82
+ * the name came from flag sniffing, and a custom or embedded connector
83
+ * whose provider exposes no recognised flag split one wallet's activity
84
+ * between "Injected Provider" and the connector's name.
85
+ *
86
+ * A RESOLVER, read at each `infoFor`, not a value: the name is live for
87
+ * the connector the integration layer bound it to (a WalletConnect
88
+ * session that resolves or changes its peer renames without a re-wrap),
89
+ * and the integration layer names events on its hook path with the same
90
+ * function, so the two paths cannot disagree. Which connector a
91
+ * provider is bound to is the integration layer's decision; it is not
92
+ * necessarily the connector that is current when the request runs.
93
+ */
94
+ this.attributions = new WeakMap();
77
95
  }
78
96
  Object.defineProperty(EvmProviderRegistry.prototype, "all", {
79
97
  // ── the provider set ─────────────────────────────────────────────────────
@@ -132,19 +150,55 @@ var EvmProviderRegistry = /** @class */ (function () {
132
150
  this.seen.add(provider);
133
151
  return true;
134
152
  };
153
+ /**
154
+ * Record (or, with `undefined`, forget) the integration layer's own
155
+ * attribution resolver for a provider. See `attributions`.
156
+ */
157
+ EvmProviderRegistry.prototype.rememberAttribution = function (provider, resolve) {
158
+ if (!provider)
159
+ return;
160
+ if (!resolve) {
161
+ this.attributions.delete(provider);
162
+ return;
163
+ }
164
+ this.attributions.set(provider, resolve);
165
+ };
166
+ /** The supplied attribution for a provider, if any resolves right now. */
167
+ EvmProviderRegistry.prototype.suppliedAttributionFor = function (provider) {
168
+ var resolve = this.attributions.get(provider);
169
+ if (!resolve)
170
+ return undefined;
171
+ try {
172
+ var info = resolve();
173
+ return (info === null || info === void 0 ? void 0 : info.name) ? info : undefined;
174
+ }
175
+ catch (_a) {
176
+ return undefined;
177
+ }
178
+ };
135
179
  /**
136
180
  * A provider's display name and rdns.
137
181
  *
138
- * EIP-6963 metadata is authoritative when we have it; otherwise fall back to
139
- * sniffing the injected provider, which is all a pre-6963 wallet offers.
182
+ * EIP-6963 metadata is authoritative when we have it. A supplied
183
+ * attribution (the connector a wagmi app connected through) comes next:
184
+ * it describes the SESSION, which is what the hook-driven events report.
185
+ * Otherwise fall back to sniffing the injected provider, which is all a
186
+ * pre-6963 wallet offers; a supplied name without an rdns keeps the
187
+ * sniffed rdns.
140
188
  */
141
189
  EvmProviderRegistry.prototype.infoFor = function (provider) {
142
190
  var announced = this.details.find(function (p) { return p.provider === provider; });
191
+ var supplied = announced
192
+ ? undefined
193
+ : this.suppliedAttributionFor(provider);
143
194
  var info = announced
144
195
  ? { name: announced.info.name, rdns: announced.info.rdns }
145
196
  : (function () {
197
+ var _a;
146
198
  var injected = detectInjectedProviderInfo(provider);
147
- return { name: injected.name, rdns: injected.rdns };
199
+ return supplied
200
+ ? { name: supplied.name, rdns: (_a = supplied.rdns) !== null && _a !== void 0 ? _a : injected.rdns }
201
+ : { name: injected.name, rdns: injected.rdns };
148
202
  })();
149
203
  // WalletConnect names the TRANSPORT; the session's peer names the
150
204
  // wallet. Resolved live, per read: a session established after the
@@ -154,7 +208,10 @@ var EvmProviderRegistry = /** @class */ (function () {
154
208
  // is included because a flagless WalletConnect-compatible provider
155
209
  // registered BEFORE its session exists detects as nothing at all;
156
210
  // the peer appearing later is itself the proof of what it was, so
157
- // the rdns upgrades with it.
211
+ // the rdns upgrades with it. A supplied name gets the same treatment
212
+ // and no more: the integration layer resolves its own peer names
213
+ // where it wants them, and a branded connector must keep its name on
214
+ // both paths.
158
215
  if (info.name === "WalletConnect" || info.name === "Injected Provider") {
159
216
  var peer = readWalletConnectPeer(provider);
160
217
  if (peer === null || peer === void 0 ? void 0 : peer.name) {
@@ -57,6 +57,18 @@ export declare class EvmRequestTracker {
57
57
  * never retry it, and every signature and transaction from that wallet
58
58
  * would be missed for the rest of the session.
59
59
  */
60
+ /** Monotonic creation stamp; owner precedence is decided by it. */
61
+ private static nextCreationSeq;
62
+ readonly creationSeq: number;
63
+ /**
64
+ * Put this tracker into an owner list at its CREATION-ORDER position.
65
+ * Registration can arrive out of order - an older instance's async wrap
66
+ * kick may resolve after a newer instance's - and dispatch picks from
67
+ * the END of the list, so append-on-registration would let resolution
68
+ * order decide which instance owns capture. Creation order is what the
69
+ * newest-live contract promises.
70
+ */
71
+ private insertBySeniority;
60
72
  registerRequestListeners(provider: EIP1193Provider): boolean;
61
73
  /** Install the wrapper function onto the provider; separated so the
62
74
  * routing shim above stays small. */
@@ -71,10 +83,15 @@ export declare class EvmRequestTracker {
71
83
  /**
72
84
  * Wallet attribution for request-derived events.
73
85
  *
74
- * Live per read through the registry, so a WalletConnect session names
75
- * its actual signer ("MetaMask Wallet", "Ledger Live") - the live-test
76
- * rows had provider_name EMPTY on every signature and transaction, which
77
- * made per-wallet activity unanswerable in the warehouse.
86
+ * Resolved through the registry at the START of each request and held
87
+ * for that request's whole lifecycle, receipt included. Reading it per
88
+ * status let a connector switch (two connectors sharing one provider) or
89
+ * a session change made while a prompt was open split one operation
90
+ * between two wallet names. Still live across requests: a WalletConnect
91
+ * session names its actual signer ("MetaMask Wallet", "Ledger Live") -
92
+ * the live-test rows had provider_name EMPTY on every signature and
93
+ * transaction, which made per-wallet activity unanswerable in the
94
+ * warehouse.
78
95
  */
79
96
  private attributionFor;
80
97
  private buildSignatureEventPayload;
@@ -137,6 +137,7 @@ var EvmRequestTracker = /** @class */ (function () {
137
137
  this.disposed = false;
138
138
  /** Providers whose owner list includes this instance; pruned on cleanup. */
139
139
  this.wrappedProviders = new Set();
140
+ this.creationSeq = EvmRequestTracker.nextCreationSeq++;
140
141
  }
141
142
  /** Stop every poll in flight. Terminal, like the event queue's close(). */
142
143
  EvmRequestTracker.prototype.cleanup = function () {
@@ -170,11 +171,24 @@ var EvmRequestTracker = /** @class */ (function () {
170
171
  this.polls.add(timer);
171
172
  };
172
173
  /**
173
- * Wrap a provider's `request`. Returns whether the wrapper is installed:
174
- * a caller that marks the provider as tracked on a false return would
175
- * never retry it, and every signature and transaction from that wallet
176
- * would be missed for the rest of the session.
174
+ * Put this tracker into an owner list at its CREATION-ORDER position.
175
+ * Registration can arrive out of order - an older instance's async wrap
176
+ * kick may resolve after a newer instance's - and dispatch picks from
177
+ * the END of the list, so append-on-registration would let resolution
178
+ * order decide which instance owns capture. Creation order is what the
179
+ * newest-live contract promises.
177
180
  */
181
+ EvmRequestTracker.prototype.insertBySeniority = function (owners) {
182
+ var _this = this;
183
+ var idx = owners.indexOf(this);
184
+ if (idx !== -1)
185
+ owners.splice(idx, 1);
186
+ var insertAt = owners.findIndex(function (o) { return o.creationSeq > _this.creationSeq; });
187
+ if (insertAt === -1)
188
+ owners.push(this);
189
+ else
190
+ owners.splice(insertAt, 0, this);
191
+ };
178
192
  EvmRequestTracker.prototype.registerRequestListeners = function (provider) {
179
193
  var _this = this;
180
194
  logger.info("registerRequestListeners");
@@ -196,10 +210,7 @@ var EvmRequestTracker = /** @class */ (function () {
196
210
  logger.warn("wrapped without owner list; cannot rebind");
197
211
  return false;
198
212
  }
199
- var idx = owners.indexOf(this);
200
- if (idx !== -1)
201
- owners.splice(idx, 1);
202
- owners.push(this);
213
+ this.insertBySeniority(owners);
203
214
  this.wrappedProviders.add(provider);
204
215
  logger.info("Provider already wrapped; rebinding the wrapper to this instance.");
205
216
  return true;
@@ -240,10 +251,7 @@ var EvmRequestTracker = /** @class */ (function () {
240
251
  var slot = provider;
241
252
  var prior = slot[WRAPPED_REQUEST_OWNER_SYMBOL];
242
253
  var owners = Array.isArray(prior) ? prior : [];
243
- var idx = owners.indexOf(this);
244
- if (idx !== -1)
245
- owners.splice(idx, 1);
246
- owners.push(this);
254
+ this.insertBySeniority(owners);
247
255
  if (!Array.isArray(prior)) {
248
256
  slot[WRAPPED_REQUEST_OWNER_SYMBOL] = owners;
249
257
  }
@@ -288,7 +296,7 @@ var EvmRequestTracker = /** @class */ (function () {
288
296
  */
289
297
  EvmRequestTracker.prototype.dispatchWrappedRequest = function (_a, provider_1, request_1) {
290
298
  return __awaiter(this, arguments, void 0, function (_b, provider, request) {
291
- var generation_1, responsePromise, capturedChainId_1, response_1, error_1, rpcError, txPromise, txChainId_1, transactionHash_1, error_2, rpcError;
299
+ var generation_1, responsePromise, capturedChainId_1, attribution_1, response_1, error_1, rpcError, txPromise, txChainId_1, attribution_2, transactionHash_1, error_2, rpcError;
292
300
  var _this = this;
293
301
  var _c, _d, _e, _f;
294
302
  var method = _b.method, params = _b.params;
@@ -331,6 +339,7 @@ var EvmRequestTracker = /** @class */ (function () {
331
339
  // below is never reported as unhandled. The real handling is there.
332
340
  responsePromise.catch(function () { return undefined; });
333
341
  capturedChainId_1 = this.registry.resolveChainId(provider);
342
+ attribution_1 = this.attributionFor(provider);
334
343
  // Fire-and-forget tracking
335
344
  (function () { return __awaiter(_this, void 0, void 0, function () {
336
345
  var e_1;
@@ -338,7 +347,7 @@ var EvmRequestTracker = /** @class */ (function () {
338
347
  switch (_a.label) {
339
348
  case 0:
340
349
  _a.trys.push([0, 2, , 3]);
341
- return [4 /*yield*/, this.deps.signature(__assign({ status: SignatureStatus.REQUESTED }, this.buildSignatureEventPayload(method, params, undefined, capturedChainId_1, provider)), this.attributionFor(provider))];
350
+ return [4 /*yield*/, this.deps.signature(__assign({ status: SignatureStatus.REQUESTED }, this.buildSignatureEventPayload(method, params, undefined, capturedChainId_1, provider)), attribution_1)];
342
351
  case 1:
343
352
  _a.sent();
344
353
  return [3 /*break*/, 3];
@@ -364,7 +373,7 @@ var EvmRequestTracker = /** @class */ (function () {
364
373
  switch (_a.label) {
365
374
  case 0:
366
375
  _a.trys.push([0, 2, , 3]);
367
- return [4 /*yield*/, this.deps.signature(__assign({ status: SignatureStatus.CONFIRMED }, this.buildSignatureEventPayload(method, params, response_1, capturedChainId_1, provider)), this.attributionFor(provider))];
376
+ return [4 /*yield*/, this.deps.signature(__assign({ status: SignatureStatus.CONFIRMED }, this.buildSignatureEventPayload(method, params, response_1, capturedChainId_1, provider)), attribution_1)];
368
377
  case 1:
369
378
  _a.sent();
370
379
  return [3 /*break*/, 3];
@@ -389,7 +398,7 @@ var EvmRequestTracker = /** @class */ (function () {
389
398
  switch (_a.label) {
390
399
  case 0:
391
400
  _a.trys.push([0, 2, , 3]);
392
- return [4 /*yield*/, this.deps.signature(__assign({ status: SignatureStatus.REJECTED }, this.buildSignatureEventPayload(method, params, undefined, capturedChainId_1, provider)), this.attributionFor(provider))];
401
+ return [4 /*yield*/, this.deps.signature(__assign({ status: SignatureStatus.REJECTED }, this.buildSignatureEventPayload(method, params, undefined, capturedChainId_1, provider)), attribution_1)];
393
402
  case 1:
394
403
  _a.sent();
395
404
  return [3 /*break*/, 3];
@@ -428,6 +437,7 @@ var EvmRequestTracker = /** @class */ (function () {
428
437
  txPromise = request({ method: method, params: params });
429
438
  txPromise.catch(function () { return undefined; });
430
439
  txChainId_1 = this.registry.resolveChainId(provider);
440
+ attribution_2 = this.attributionFor(provider);
431
441
  (function () { return __awaiter(_this, void 0, void 0, function () {
432
442
  var payload, e_4;
433
443
  return __generator(this, function (_a) {
@@ -437,7 +447,7 @@ var EvmRequestTracker = /** @class */ (function () {
437
447
  return [4 /*yield*/, this.buildTransactionEventPayload(params, provider, txChainId_1)];
438
448
  case 1:
439
449
  payload = _a.sent();
440
- return [4 /*yield*/, this.deps.transaction(__assign({ status: TransactionStatus.STARTED }, payload), this.attributionFor(provider))];
450
+ return [4 /*yield*/, this.deps.transaction(__assign({ status: TransactionStatus.STARTED }, payload), attribution_2)];
441
451
  case 2:
442
452
  _a.sent();
443
453
  return [3 /*break*/, 4];
@@ -464,11 +474,11 @@ var EvmRequestTracker = /** @class */ (function () {
464
474
  return [4 /*yield*/, this.buildTransactionEventPayload(params, provider, txChainId_1)];
465
475
  case 1:
466
476
  payload = _a.sent();
467
- return [4 /*yield*/, this.deps.transaction(__assign(__assign({ status: TransactionStatus.BROADCASTED }, payload), { transactionHash: transactionHash_1 }), this.attributionFor(provider))];
477
+ return [4 /*yield*/, this.deps.transaction(__assign(__assign({ status: TransactionStatus.BROADCASTED }, payload), { transactionHash: transactionHash_1 }), attribution_2)];
468
478
  case 2:
469
479
  _a.sent();
470
480
  // Start async polling for transaction receipt
471
- this.pollTransactionReceipt(provider, transactionHash_1, payload);
481
+ this.pollTransactionReceipt(provider, transactionHash_1, payload, attribution_2);
472
482
  return [3 /*break*/, 4];
473
483
  case 3:
474
484
  e_5 = _a.sent();
@@ -493,7 +503,7 @@ var EvmRequestTracker = /** @class */ (function () {
493
503
  return [4 /*yield*/, this.buildTransactionEventPayload(params, provider, txChainId_1)];
494
504
  case 1:
495
505
  payload = _a.sent();
496
- return [4 /*yield*/, this.deps.transaction(__assign({ status: TransactionStatus.REJECTED }, payload), this.attributionFor(provider))];
506
+ return [4 /*yield*/, this.deps.transaction(__assign({ status: TransactionStatus.REJECTED }, payload), attribution_2)];
497
507
  case 2:
498
508
  _a.sent();
499
509
  return [3 /*break*/, 4];
@@ -515,10 +525,15 @@ var EvmRequestTracker = /** @class */ (function () {
515
525
  /**
516
526
  * Wallet attribution for request-derived events.
517
527
  *
518
- * Live per read through the registry, so a WalletConnect session names
519
- * its actual signer ("MetaMask Wallet", "Ledger Live") - the live-test
520
- * rows had provider_name EMPTY on every signature and transaction, which
521
- * made per-wallet activity unanswerable in the warehouse.
528
+ * Resolved through the registry at the START of each request and held
529
+ * for that request's whole lifecycle, receipt included. Reading it per
530
+ * status let a connector switch (two connectors sharing one provider) or
531
+ * a session change made while a prompt was open split one operation
532
+ * between two wallet names. Still live across requests: a WalletConnect
533
+ * session names its actual signer ("MetaMask Wallet", "Ledger Live") -
534
+ * the live-test rows had provider_name EMPTY on every signature and
535
+ * transaction, which made per-wallet activity unanswerable in the
536
+ * warehouse.
522
537
  */
523
538
  EvmRequestTracker.prototype.attributionFor = function (provider) {
524
539
  var info = this.registry.infoFor(provider);
@@ -588,8 +603,11 @@ var EvmRequestTracker = /** @class */ (function () {
588
603
  /**
589
604
  * Polls for transaction receipt and emits tx.status = CONFIRMED or REVERTED.
590
605
  */
591
- EvmRequestTracker.prototype.pollTransactionReceipt = function (provider_1, transactionHash_2, payload_1) {
592
- return __awaiter(this, arguments, void 0, function (provider, transactionHash, payload, maxAttempts, intervalMs) {
606
+ EvmRequestTracker.prototype.pollTransactionReceipt = function (provider_1, transactionHash_2, payload_1, attribution_3) {
607
+ return __awaiter(this, arguments, void 0, function (provider, transactionHash, payload,
608
+ // Snapshot from the broadcast: a connector or session change during
609
+ // the poll window must not relabel the receipt.
610
+ attribution, maxAttempts, intervalMs) {
593
611
  var attempts, poll;
594
612
  var _this = this;
595
613
  if (maxAttempts === void 0) { maxAttempts = 10; }
@@ -618,7 +636,7 @@ var EvmRequestTracker = /** @class */ (function () {
618
636
  // status: 1 = success, 0 = reverted
619
637
  if (receipt.status === "0x1" || receipt.status === 1) {
620
638
  this.deps
621
- .transaction(__assign(__assign({ status: TransactionStatus.CONFIRMED }, payload), { transactionHash: transactionHash }), this.attributionFor(provider))
639
+ .transaction(__assign(__assign({ status: TransactionStatus.CONFIRMED }, payload), { transactionHash: transactionHash }), attribution)
622
640
  .catch(function (e) {
623
641
  return logger.error("Formo: Failed to track transaction confirmation", e);
624
642
  });
@@ -626,7 +644,7 @@ var EvmRequestTracker = /** @class */ (function () {
626
644
  }
627
645
  else if (receipt.status === "0x0" || receipt.status === 0) {
628
646
  this.deps
629
- .transaction(__assign(__assign({ status: TransactionStatus.REVERTED }, payload), { transactionHash: transactionHash }), this.attributionFor(provider))
647
+ .transaction(__assign(__assign({ status: TransactionStatus.REVERTED }, payload), { transactionHash: transactionHash }), attribution)
630
648
  .catch(function (e) {
631
649
  return logger.error("Formo: Failed to track transaction revert", e);
632
650
  });
@@ -848,6 +866,14 @@ var EvmRequestTracker = /** @class */ (function () {
848
866
  });
849
867
  });
850
868
  };
869
+ /**
870
+ * Wrap a provider's `request`. Returns whether the wrapper is installed:
871
+ * a caller that marks the provider as tracked on a false return would
872
+ * never retry it, and every signature and transaction from that wallet
873
+ * would be missed for the rest of the session.
874
+ */
875
+ /** Monotonic creation stamp; owner precedence is decided by it. */
876
+ EvmRequestTracker.nextCreationSeq = 0;
851
877
  return EvmRequestTracker;
852
878
  }());
853
879
  export { EvmRequestTracker };
@@ -1,2 +1,2 @@
1
- export declare const version = "1.38.0";
1
+ export declare const version = "1.38.2";
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.38.0';
3
+ export var version = '1.38.2';
4
4
  //# sourceMappingURL=version.js.map
@@ -6,7 +6,7 @@
6
6
  * wrapping approach when Wagmi mode is enabled.
7
7
  */
8
8
  import { FormoAnalytics } from "../FormoAnalytics";
9
- import { WagmiConfig, QueryClient } from "./types";
9
+ import { QueryClient, WagmiConfig } from "./types";
10
10
  /**
11
11
  * How long the markers stay trustworthy after the last handler goes away.
12
12
  *
@@ -337,6 +337,35 @@ export declare class WagmiEventHandler {
337
337
  * (still connected through its own connector).
338
338
  */
339
339
  private isAddressConnected;
340
+ /**
341
+ * A specific connector's name and rdns, for the fallback-wrapped
342
+ * provider's request-derived events.
343
+ *
344
+ * The NAME is exactly what the hook path emits for that connector
345
+ * (`getConnectorName`: the live WalletConnect peer for a WalletConnect
346
+ * connector, the connector's own name otherwise), so a branded connector
347
+ * keeps its name on both paths and a session that changes wallets
348
+ * renames on both. The rdns is the connector's when wagmi knows it as
349
+ * ONE value (EIP-6963 discovered connectors carry theirs, some as a
350
+ * one-element list); a connector that matches several rdns values does
351
+ * not say which one this provider is, so nothing is passed and the
352
+ * registry keeps the sniffed one.
353
+ */
354
+ private attributionForConnector;
355
+ /**
356
+ * Resolver handed to the registry at wrap time, read at each request
357
+ * start. BOUND to the connector whose `getProvider` resolved to the
358
+ * wrapped provider, not to whichever connector is current: an app can
359
+ * keep a wallet client over a previous connector's provider and issue a
360
+ * request through it after switching, and that request belongs to the
361
+ * wallet that handles it. The peer name is still read live. A provider
362
+ * SHARED by two connectors is re-bound when the new connector's
363
+ * resolution lands (one microtask for an injected connector); a request
364
+ * issued inside that gap keeps the previous label.
365
+ */
366
+ private boundConnectorAttribution;
367
+ /** `getConnectorName` for a SPECIFIC connector, current or not. */
368
+ private nameForConnector;
340
369
  /**
341
370
  * Get the connector name from Wagmi state
342
371
  */
@@ -362,6 +391,43 @@ export declare class WagmiEventHandler {
362
391
  * dedup. Fire-and-forget per connection; a provider that cannot be
363
392
  * produced simply keeps mutation-only capture.
364
393
  */
394
+ /**
395
+ * Connections THIS instance has wrapped. Deliberately per-instance, not
396
+ * module-level: a module-level guard let a rebuilt SDK instance skip
397
+ * re-wrapping, so ownership stayed with the torn-down instance and every
398
+ * capture died in its closed queue - and it also stopped a second
399
+ * write-key instance from ever registering. Re-wrapping is safe and
400
+ * cheap: the request tracker rebinds ownership of an intact wrapper.
401
+ */
402
+ /**
403
+ * Latest wrap attempt per connector. Every kick re-resolves
404
+ * getProvider() - a connector can hand out a REPLACEMENT provider after
405
+ * a reconnect, so a once-only guard would leave the new session's
406
+ * provider unwrapped forever. Re-wrapping is idempotent: the request
407
+ * tracker rebinds ownership of an intact wrapper. The epoch lets a slow
408
+ * resolution from a superseded kick (an earlier session, an earlier
409
+ * chain) be discarded instead of overwriting fresher state.
410
+ */
411
+ private wrapEpochs;
412
+ /** Consecutive automatic wrap retries per connector; see below. */
413
+ private wrapRetryCounts;
414
+ /** Pending retry timers, cancelled by cleanup(). */
415
+ private wrapRetryTimers;
416
+ /**
417
+ * Bumped on every observed disconnect. Every wrap attempt captures it
418
+ * at kick time and its resolution stands down on a mismatch, so a
419
+ * disconnect invalidates ALL pending wraps at once - including ones
420
+ * whose getProvider() had not resolved yet, which no per-connector
421
+ * bookkeeping can reach because nothing has been recorded for them.
422
+ */
423
+ private wrapSessionGeneration;
424
+ /** The active connector this instance wrapped, and its provider, for
425
+ * chain updates. Kept as a pair so a chain report is only ever applied
426
+ * to the provider of the connector it describes. Keyed by connector,
427
+ * not by connection record: wagmi REPLACES the connection object on
428
+ * every account or chain update, so record identity is not stable. */
429
+ private fallbackConnector?;
430
+ private fallbackProvider?;
365
431
  private wrapActiveConnectorProvider;
366
432
  private kickWalletConnectPeerLookup;
367
433
  /**