@formo/analytics 1.19.7 → 1.19.9

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.
@@ -22,6 +22,7 @@ export declare class FormoAnalytics implements IFormoAnalytics {
22
22
  */
23
23
  private _trackedProviders;
24
24
  private _injectedProviderDetail?;
25
+ private _processingAccountsChanged;
25
26
  private _seenProviders;
26
27
  config: Config;
27
28
  currentChainId?: ChainID;
@@ -181,6 +182,17 @@ export declare class FormoAnalytics implements IFormoAnalytics {
181
182
  private addProviderListener;
182
183
  private registerAccountsChangedListener;
183
184
  private onAccountsChanged;
185
+ /**
186
+ * Handles changes to the accounts of a given EIP-1193 provider.
187
+ *
188
+ * @param provider - The EIP-1193 provider whose accounts have changed.
189
+ * @param accounts - The new array of account addresses. An empty array indicates a disconnect.
190
+ * @returns A promise that resolves when the account change has been processed.
191
+ *
192
+ * If the accounts array is empty and the provider is the active provider, this method triggers
193
+ * a disconnect flow. Otherwise, it updates the state to reflect the new accounts as needed.
194
+ */
195
+ private _handleAccountsChanged;
184
196
  private registerChainChangedListener;
185
197
  private onChainChanged;
186
198
  private registerConnectListener;
@@ -257,6 +269,11 @@ export declare class FormoAnalytics implements IFormoAnalytics {
257
269
  * @returns The checksummed address or undefined if invalid
258
270
  */
259
271
  private validateAndChecksumAddress;
272
+ /**
273
+ * Helper method to clear the active provider state
274
+ * Centralizes provider clearing logic for consistency
275
+ */
276
+ private clearActiveProvider;
260
277
  /**
261
278
  * Helper method to safely add a provider detail to _providers array, ensuring no duplicates
262
279
  * @param detail The provider detail to add
@@ -65,6 +65,14 @@ var utils_1 = require("./utils");
65
65
  var address_1 = require("./utils/address");
66
66
  var validators_1 = require("./validators");
67
67
  var chain_1 = require("./utils/chain");
68
+ /**
69
+ * Constants for provider switching reasons
70
+ */
71
+ var PROVIDER_SWITCH_REASONS = {
72
+ ADDRESS_MISMATCH: "Address mismatch indicates wallet switch",
73
+ NO_ACCOUNTS: "Current provider has no accounts",
74
+ CHECK_FAILED: "Could not check current provider accounts"
75
+ };
68
76
  var FormoAnalytics = /** @class */ (function () {
69
77
  function FormoAnalytics(writeKey, options) {
70
78
  if (options === void 0) { options = {}; }
@@ -86,6 +94,8 @@ var FormoAnalytics = /** @class */ (function () {
86
94
  * - A provider can be tracked but later removed from discovery
87
95
  */
88
96
  this._trackedProviders = new Set();
97
+ // Flag to prevent concurrent processing of accountsChanged events
98
+ this._processingAccountsChanged = false;
89
99
  // Set to efficiently track seen providers for deduplication and O(1) lookup
90
100
  this._seenProviders = new Set();
91
101
  this.currentUserId = "";
@@ -209,6 +219,7 @@ var FormoAnalytics = /** @class */ (function () {
209
219
  (0, lib_1.cookie)().remove(constants_1.LOCAL_ANONYMOUS_ID_KEY);
210
220
  (0, lib_1.cookie)().remove(constants_1.SESSION_USER_ID_KEY);
211
221
  (0, lib_1.cookie)().remove(constants_1.SESSION_WALLET_DETECTED_KEY);
222
+ (0, lib_1.cookie)().remove(constants_1.SESSION_WALLET_IDENTIFIED_KEY);
212
223
  };
213
224
  /**
214
225
  * Emits a connect wallet event.
@@ -285,7 +296,8 @@ var FormoAnalytics = /** @class */ (function () {
285
296
  _a.sent();
286
297
  this.currentAddress = undefined;
287
298
  this.currentChainId = undefined;
288
- lib_1.logger.info("Wallet disconnected: Cleared currentAddress and currentChainId");
299
+ this.clearActiveProvider();
300
+ lib_1.logger.info("Wallet disconnected: Cleared currentAddress, currentChainId, and provider");
289
301
  return [2 /*return*/];
290
302
  }
291
303
  });
@@ -395,51 +407,58 @@ var FormoAnalytics = /** @class */ (function () {
395
407
  */
396
408
  FormoAnalytics.prototype.identify = function (params, properties, context, callback) {
397
409
  return __awaiter(this, void 0, void 0, function () {
398
- var _i, _a, providerDetail, provider, address_2, err_1, userId, address, providerName, rdns, validAddress, e_1;
410
+ var _i, _a, providerDetail, provider, address_2, validAddress_1, err_1, userId, address, providerName, rdns, validAddress, e_1;
399
411
  var _b;
400
412
  return __generator(this, function (_c) {
401
413
  switch (_c.label) {
402
414
  case 0:
403
- _c.trys.push([0, 11, , 12]);
404
- if (!!params) return [3 /*break*/, 9];
415
+ _c.trys.push([0, 12, , 13]);
416
+ if (!!params) return [3 /*break*/, 10];
405
417
  // If no params provided, auto-identify
406
418
  lib_1.logger.info("Auto-identifying with providers:", this._providers.map(function (p) { return p.info.name; }));
407
419
  _i = 0, _a = this._providers;
408
420
  _c.label = 1;
409
421
  case 1:
410
- if (!(_i < _a.length)) return [3 /*break*/, 8];
422
+ if (!(_i < _a.length)) return [3 /*break*/, 9];
411
423
  providerDetail = _a[_i];
412
424
  provider = providerDetail.provider;
413
425
  if (!provider)
414
- return [3 /*break*/, 7];
426
+ return [3 /*break*/, 8];
415
427
  _c.label = 2;
416
428
  case 2:
417
- _c.trys.push([2, 6, , 7]);
429
+ _c.trys.push([2, 7, , 8]);
418
430
  return [4 /*yield*/, this.getAddress(provider)];
419
431
  case 3:
420
432
  address_2 = _c.sent();
421
- if (!address_2) return [3 /*break*/, 5];
422
- lib_1.logger.info("Auto-identifying", address_2, providerDetail.info.name, providerDetail.info.rdns);
433
+ if (!address_2) return [3 /*break*/, 6];
434
+ validAddress_1 = this.validateAndChecksumAddress(address_2);
435
+ if (!(validAddress_1 && !this.session.isWalletIdentified(validAddress_1, providerDetail.info.rdns))) return [3 /*break*/, 5];
436
+ lib_1.logger.info("Auto-identifying", validAddress_1, providerDetail.info.name, providerDetail.info.rdns);
423
437
  // NOTE: do not set this.currentAddress without explicit connect or identify
424
438
  return [4 /*yield*/, this.identify({
425
- address: address_2,
439
+ address: validAddress_1,
426
440
  providerName: providerDetail.info.name,
427
441
  rdns: providerDetail.info.rdns,
428
442
  }, properties, context, callback)];
429
443
  case 4:
430
444
  // NOTE: do not set this.currentAddress without explicit connect or identify
431
445
  _c.sent();
432
- _c.label = 5;
433
- case 5: return [3 /*break*/, 7];
434
- case 6:
446
+ return [3 /*break*/, 6];
447
+ case 5:
448
+ if (validAddress_1) {
449
+ lib_1.logger.info("Auto-identify: Skipping already identified wallet", validAddress_1, providerDetail.info.name, providerDetail.info.rdns);
450
+ }
451
+ _c.label = 6;
452
+ case 6: return [3 /*break*/, 8];
453
+ case 7:
435
454
  err_1 = _c.sent();
436
455
  lib_1.logger.error("Failed to identify provider ".concat(providerDetail.info.name, ":"), err_1);
437
- return [3 /*break*/, 7];
438
- case 7:
456
+ return [3 /*break*/, 8];
457
+ case 8:
439
458
  _i++;
440
459
  return [3 /*break*/, 1];
441
- case 8: return [2 /*return*/];
442
- case 9:
460
+ case 9: return [2 /*return*/];
461
+ case 10:
443
462
  userId = params.userId, address = params.address, providerName = params.providerName, rdns = params.rdns;
444
463
  lib_1.logger.info("Identify", address, userId, providerName, rdns);
445
464
  validAddress = undefined;
@@ -457,20 +476,29 @@ var FormoAnalytics = /** @class */ (function () {
457
476
  this.currentUserId = userId;
458
477
  (0, lib_1.cookie)().set(constants_1.SESSION_USER_ID_KEY, userId);
459
478
  }
479
+ // Check for duplicate identify events in this session
480
+ if (validAddress && rdns && this.session.isWalletIdentified(validAddress, rdns)) {
481
+ lib_1.logger.warn("Identify: Wallet ".concat(providerName || 'Unknown', " with address ").concat(validAddress, " already identified in this session"));
482
+ return [2 /*return*/];
483
+ }
484
+ // Mark as identified before emitting the event
485
+ if (validAddress && rdns) {
486
+ this.session.markWalletIdentified(validAddress, rdns);
487
+ }
460
488
  return [4 /*yield*/, this.trackEvent(constants_1.EventType.IDENTIFY, {
461
489
  address: validAddress,
462
490
  providerName: providerName,
463
491
  userId: userId,
464
492
  rdns: rdns,
465
493
  }, properties, context, callback)];
466
- case 10:
467
- _c.sent();
468
- return [3 /*break*/, 12];
469
494
  case 11:
495
+ _c.sent();
496
+ return [3 /*break*/, 13];
497
+ case 12:
470
498
  e_1 = _c.sent();
471
499
  lib_1.logger.log("identify error", e_1);
472
- return [3 /*break*/, 12];
473
- case 12: return [2 /*return*/];
500
+ return [3 /*break*/, 13];
501
+ case 13: return [2 /*return*/];
474
502
  }
475
503
  });
476
504
  });
@@ -583,12 +611,49 @@ var FormoAnalytics = /** @class */ (function () {
583
611
  };
584
612
  FormoAnalytics.prototype.onAccountsChanged = function (provider, accounts) {
585
613
  return __awaiter(this, void 0, void 0, function () {
586
- var error_1, address, nextChainId, wasDisconnected, isProviderSwitch, hadPreviousConnection, error_2, providerInfo, effectiveChainId;
587
- var _a, _b, _c;
588
- return __generator(this, function (_d) {
589
- switch (_d.label) {
614
+ return __generator(this, function (_a) {
615
+ switch (_a.label) {
590
616
  case 0:
591
617
  lib_1.logger.info("onAccountsChanged", accounts);
618
+ // Prevent concurrent processing of accountsChanged events to avoid race conditions
619
+ if (this._processingAccountsChanged) {
620
+ lib_1.logger.debug("OnAccountsChanged: Already processing accountsChanged, skipping", {
621
+ provider: this.getProviderInfo(provider).name
622
+ });
623
+ return [2 /*return*/];
624
+ }
625
+ this._processingAccountsChanged = true;
626
+ _a.label = 1;
627
+ case 1:
628
+ _a.trys.push([1, , 3, 4]);
629
+ return [4 /*yield*/, this._handleAccountsChanged(provider, accounts)];
630
+ case 2:
631
+ _a.sent();
632
+ return [3 /*break*/, 4];
633
+ case 3:
634
+ this._processingAccountsChanged = false;
635
+ return [7 /*endfinally*/];
636
+ case 4: return [2 /*return*/];
637
+ }
638
+ });
639
+ });
640
+ };
641
+ /**
642
+ * Handles changes to the accounts of a given EIP-1193 provider.
643
+ *
644
+ * @param provider - The EIP-1193 provider whose accounts have changed.
645
+ * @param accounts - The new array of account addresses. An empty array indicates a disconnect.
646
+ * @returns A promise that resolves when the account change has been processed.
647
+ *
648
+ * If the accounts array is empty and the provider is the active provider, this method triggers
649
+ * a disconnect flow. Otherwise, it updates the state to reflect the new accounts as needed.
650
+ */
651
+ FormoAnalytics.prototype._handleAccountsChanged = function (provider, accounts) {
652
+ return __awaiter(this, void 0, void 0, function () {
653
+ var error_1, address, currentStoredAddress, newProviderAddress, activeProviderAccounts, error_2, nextChainId, wasDisconnected, providerInfo, effectiveChainId;
654
+ return __generator(this, function (_a) {
655
+ switch (_a.label) {
656
+ case 0:
592
657
  if (!(accounts.length === 0)) return [3 /*break*/, 7];
593
658
  if (!(this._provider === provider)) return [3 /*break*/, 5];
594
659
  lib_1.logger.info("OnAccountsChanged: Detecting disconnect, current state:", {
@@ -596,9 +661,9 @@ var FormoAnalytics = /** @class */ (function () {
596
661
  currentChainId: this.currentChainId,
597
662
  providerMatch: this._provider === provider
598
663
  });
599
- _d.label = 1;
664
+ _a.label = 1;
600
665
  case 1:
601
- _d.trys.push([1, 3, , 4]);
666
+ _a.trys.push([1, 3, , 4]);
602
667
  // Pass current state explicitly to ensure we have the data for the disconnect event
603
668
  return [4 /*yield*/, this.disconnect({
604
669
  chainId: this.currentChainId,
@@ -606,16 +671,16 @@ var FormoAnalytics = /** @class */ (function () {
606
671
  })];
607
672
  case 2:
608
673
  // Pass current state explicitly to ensure we have the data for the disconnect event
609
- _d.sent();
674
+ _a.sent();
610
675
  return [3 /*break*/, 4];
611
676
  case 3:
612
- error_1 = _d.sent();
677
+ error_1 = _a.sent();
613
678
  lib_1.logger.error("Failed to disconnect provider on accountsChanged", error_1);
614
679
  return [3 /*break*/, 4];
615
680
  case 4: return [3 /*break*/, 6];
616
681
  case 5:
617
682
  lib_1.logger.info("OnAccountsChanged: Ignoring disconnect for non-active provider");
618
- _d.label = 6;
683
+ _a.label = 6;
619
684
  case 6: return [2 /*return*/];
620
685
  case 7:
621
686
  address = this.validateAndChecksumAddress(accounts[0]);
@@ -623,54 +688,106 @@ var FormoAnalytics = /** @class */ (function () {
623
688
  lib_1.logger.warn("onAccountsChanged: Invalid address received", accounts[0]);
624
689
  return [2 /*return*/];
625
690
  }
626
- // If both the provider and address are the same, no-op. Allow provider switches even if address is the same.
627
- if (this._provider === provider && address === this.currentAddress) {
628
- return [2 /*return*/];
629
- }
630
- return [4 /*yield*/, this.getCurrentChainId(provider)];
631
- case 8:
632
- nextChainId = _d.sent();
633
- wasDisconnected = !this.currentAddress;
634
- isProviderSwitch = this._provider && this._provider !== provider;
635
- lib_1.logger.info("OnAccountsChanged: Provider switching analysis:", {
636
- currentProvider: ((_b = (_a = this._provider) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name) || 'none',
637
- newProvider: ((_c = provider === null || provider === void 0 ? void 0 : provider.constructor) === null || _c === void 0 ? void 0 : _c.name) || 'unknown',
638
- currentAddress: this.currentAddress,
639
- wasDisconnected: wasDisconnected,
640
- isProviderMismatch: isProviderSwitch
691
+ if (!(this._provider && this._provider !== provider)) return [3 /*break*/, 18];
692
+ currentStoredAddress = this.currentAddress;
693
+ newProviderAddress = this.validateAndChecksumAddress(address);
694
+ lib_1.logger.info("OnAccountsChanged: Different provider attempting to connect", {
695
+ activeProvider: this.getProviderInfo(this._provider).name,
696
+ eventProvider: this.getProviderInfo(provider).name,
697
+ currentStoredAddress: currentStoredAddress,
698
+ newProviderAddress: newProviderAddress
641
699
  });
642
- if (!isProviderSwitch) return [3 /*break*/, 13];
643
- hadPreviousConnection = !!this.currentAddress;
644
- if (!hadPreviousConnection) return [3 /*break*/, 12];
645
- lib_1.logger.info("OnAccountsChanged: Detected provider switch with existing connection - emitting disconnect for previous provider");
646
- _d.label = 9;
700
+ _a.label = 8;
701
+ case 8:
702
+ _a.trys.push([8, 16, , 18]);
703
+ return [4 /*yield*/, this.getAccounts(this._provider)];
647
704
  case 9:
648
- _d.trys.push([9, 11, , 12]);
705
+ activeProviderAccounts = _a.sent();
706
+ lib_1.logger.info("OnAccountsChanged: Checking current provider accounts", {
707
+ activeProvider: this.getProviderInfo(this._provider).name,
708
+ accountsLength: activeProviderAccounts ? activeProviderAccounts.length : 0,
709
+ accounts: activeProviderAccounts
710
+ });
711
+ if (!(activeProviderAccounts && activeProviderAccounts.length > 0)) return [3 /*break*/, 13];
712
+ if (!(newProviderAddress && currentStoredAddress && newProviderAddress !== currentStoredAddress)) return [3 /*break*/, 11];
713
+ lib_1.logger.info("OnAccountsChanged: Different address detected, switching providers despite current provider having accounts", {
714
+ activeProvider: this.getProviderInfo(this._provider).name,
715
+ eventProvider: this.getProviderInfo(provider).name,
716
+ currentAddress: currentStoredAddress,
717
+ newAddress: newProviderAddress,
718
+ reason: PROVIDER_SWITCH_REASONS.ADDRESS_MISMATCH
719
+ });
720
+ // Emit disconnect for the old provider
649
721
  return [4 /*yield*/, this.disconnect({
650
722
  chainId: this.currentChainId,
651
723
  address: this.currentAddress
652
724
  })];
653
725
  case 10:
654
- _d.sent();
726
+ // Emit disconnect for the old provider
727
+ _a.sent();
728
+ // Clear state and let the new provider become active
729
+ this.clearActiveProvider();
655
730
  return [3 /*break*/, 12];
656
731
  case 11:
657
- error_2 = _d.sent();
658
- lib_1.logger.error("Failed to emit disconnect during provider switch:", error_2);
659
- return [3 /*break*/, 12];
660
- case 12:
661
- // Validate that the new provider is in a valid state before switching
662
- if (this.isProviderInValidState(provider)) {
663
- lib_1.logger.info("OnAccountsChanged: Handling provider mismatch - switching providers");
664
- this.handleProviderMismatch(provider);
732
+ lib_1.logger.info("OnAccountsChanged: Current provider still has accounts and same address, ignoring new provider", {
733
+ activeProvider: this.getProviderInfo(this._provider).name,
734
+ eventProvider: this.getProviderInfo(provider).name,
735
+ activeProviderAccountsCount: activeProviderAccounts.length,
736
+ currentAddress: currentStoredAddress,
737
+ newAddress: newProviderAddress
738
+ });
739
+ return [2 /*return*/];
740
+ case 12: return [3 /*break*/, 15];
741
+ case 13:
742
+ lib_1.logger.info("OnAccountsChanged: Current provider has no accounts, switching to new provider", {
743
+ oldProvider: this.getProviderInfo(this._provider).name,
744
+ newProvider: this.getProviderInfo(provider).name,
745
+ reason: PROVIDER_SWITCH_REASONS.NO_ACCOUNTS
746
+ });
747
+ // Emit disconnect for the old provider that didn't signal properly
748
+ return [4 /*yield*/, this.disconnect({
749
+ chainId: this.currentChainId,
750
+ address: this.currentAddress
751
+ })];
752
+ case 14:
753
+ // Emit disconnect for the old provider that didn't signal properly
754
+ _a.sent();
755
+ // Clear state and let the new provider become active
756
+ this.clearActiveProvider();
757
+ _a.label = 15;
758
+ case 15: return [3 /*break*/, 18];
759
+ case 16:
760
+ error_2 = _a.sent();
761
+ lib_1.logger.warn("OnAccountsChanged: Could not check current provider accounts, switching to new provider", {
762
+ error: error_2 instanceof Error ? error_2.message : String(error_2),
763
+ errorType: error_2 instanceof Error ? error_2.constructor.name : typeof error_2,
764
+ oldProvider: this._provider ? this.getProviderInfo(this._provider).name : 'unknown',
765
+ newProvider: this.getProviderInfo(provider).name,
766
+ reason: PROVIDER_SWITCH_REASONS.CHECK_FAILED
767
+ });
768
+ // If we can't check the current provider, assume it's disconnected
769
+ return [4 /*yield*/, this.disconnect({
770
+ chainId: this.currentChainId,
771
+ address: this.currentAddress
772
+ })];
773
+ case 17:
774
+ // If we can't check the current provider, assume it's disconnected
775
+ _a.sent();
776
+ this.clearActiveProvider();
777
+ return [3 /*break*/, 18];
778
+ case 18:
779
+ // Set provider if none exists (first connection)
780
+ if (!this._provider) {
781
+ this._provider = provider;
665
782
  }
666
- else {
667
- lib_1.logger.warn("Provider switching blocked: new provider is not in a valid state");
783
+ // If both the provider and address are the same, no-op
784
+ if (this._provider === provider && address === this.currentAddress) {
668
785
  return [2 /*return*/];
669
786
  }
670
- _d.label = 13;
671
- case 13:
672
- // Commit new active provider and state
673
- this._provider = provider;
787
+ return [4 /*yield*/, this.getCurrentChainId(provider)];
788
+ case 19:
789
+ nextChainId = _a.sent();
790
+ wasDisconnected = !this.currentAddress;
674
791
  this.currentAddress = address;
675
792
  this.currentChainId = nextChainId;
676
793
  providerInfo = this.getProviderInfo(provider);
@@ -678,7 +795,6 @@ var FormoAnalytics = /** @class */ (function () {
678
795
  chainId: nextChainId,
679
796
  address: address,
680
797
  wasDisconnected: wasDisconnected,
681
- isProviderSwitch: isProviderSwitch,
682
798
  providerName: providerInfo.name,
683
799
  rdns: providerInfo.rdns,
684
800
  hasChainId: !!nextChainId
@@ -801,7 +917,7 @@ var FormoAnalytics = /** @class */ (function () {
801
917
  };
802
918
  FormoAnalytics.prototype.onConnected = function (provider, connection) {
803
919
  return __awaiter(this, void 0, void 0, function () {
804
- var chainId, address, wasDisconnected, providerInfo, effectiveChainId, e_3;
920
+ var chainId, address, wasDisconnected, isActiveProvider, providerInfo, effectiveChainId, providerInfo, e_3;
805
921
  return __generator(this, function (_a) {
806
922
  switch (_a.label) {
807
923
  case 0:
@@ -821,17 +937,21 @@ var FormoAnalytics = /** @class */ (function () {
821
937
  if (!this._provider) {
822
938
  this._provider = provider;
823
939
  }
824
- this.currentChainId = chainId;
825
- this.currentAddress = this.validateAndChecksumAddress(address) || undefined;
826
- // Always emit connect event for better analytics capture
827
- if (this.currentAddress) {
940
+ isActiveProvider = this._provider === provider;
941
+ // Only update global state (chainId/address) from the active provider
942
+ if (isActiveProvider) {
943
+ this.currentChainId = chainId;
944
+ this.currentAddress = this.validateAndChecksumAddress(address) || undefined;
945
+ }
946
+ if (isActiveProvider && this.currentAddress) {
828
947
  providerInfo = this.getProviderInfo(provider);
829
948
  lib_1.logger.info("OnConnected: Detected wallet connection, emitting connect event", {
830
949
  chainId: chainId,
831
950
  wasDisconnected: wasDisconnected,
832
951
  providerName: providerInfo.name,
833
952
  rdns: providerInfo.rdns,
834
- hasChainId: !!chainId
953
+ hasChainId: !!chainId,
954
+ isActiveProvider: isActiveProvider
835
955
  });
836
956
  effectiveChainId = chainId || 0;
837
957
  if (effectiveChainId === 0) {
@@ -847,6 +967,16 @@ var FormoAnalytics = /** @class */ (function () {
847
967
  lib_1.logger.error("Failed to track connect event during provider connection:", error);
848
968
  });
849
969
  }
970
+ else if (address && !isActiveProvider) {
971
+ providerInfo = this.getProviderInfo(provider);
972
+ lib_1.logger.debug("OnConnected: Skipping connect event for non-active provider", {
973
+ chainId: chainId,
974
+ providerName: providerInfo.name,
975
+ rdns: providerInfo.rdns,
976
+ isActiveProvider: isActiveProvider,
977
+ activeProviderInfo: this._provider ? this.getProviderInfo(this._provider) : null
978
+ });
979
+ }
850
980
  }
851
981
  return [3 /*break*/, 4];
852
982
  case 3:
@@ -1609,7 +1739,7 @@ var FormoAnalytics = /** @class */ (function () {
1609
1739
  this.removeProviderListeners(provider);
1610
1740
  this._trackedProviders.delete(provider);
1611
1741
  if (this._provider === provider) {
1612
- this._provider = undefined;
1742
+ this.clearActiveProvider();
1613
1743
  }
1614
1744
  }
1615
1745
  catch (e) {
@@ -1681,6 +1811,13 @@ var FormoAnalytics = /** @class */ (function () {
1681
1811
  var validAddress = (0, address_1.getValidAddress)(address);
1682
1812
  return validAddress ? (0, utils_1.toChecksumAddress)(validAddress) : undefined;
1683
1813
  };
1814
+ /**
1815
+ * Helper method to clear the active provider state
1816
+ * Centralizes provider clearing logic for consistency
1817
+ */
1818
+ FormoAnalytics.prototype.clearActiveProvider = function () {
1819
+ this._provider = undefined;
1820
+ };
1684
1821
  /**
1685
1822
  * Helper method to safely add a provider detail to _providers array, ensuring no duplicates
1686
1823
  * @param detail The provider detail to add
@@ -1718,12 +1855,33 @@ var FormoAnalyticsSession = /** @class */ (function () {
1718
1855
  FormoAnalyticsSession.prototype.markWalletDetected = function (rdns) {
1719
1856
  var _a;
1720
1857
  var rdnses = ((_a = (0, lib_1.cookie)().get(constants_1.SESSION_WALLET_DETECTED_KEY)) === null || _a === void 0 ? void 0 : _a.split(",")) || [];
1721
- rdnses.push(rdns);
1722
- (0, lib_1.cookie)().set(constants_1.SESSION_WALLET_DETECTED_KEY, rdnses.join(","), {
1723
- // by the end of the day
1724
- expires: new Date(Date.now() + 86400 * 1000).toUTCString(),
1725
- path: "/",
1726
- });
1858
+ if (!rdnses.includes(rdns)) {
1859
+ rdnses.push(rdns);
1860
+ (0, lib_1.cookie)().set(constants_1.SESSION_WALLET_DETECTED_KEY, rdnses.join(","), {
1861
+ // by the end of the day
1862
+ expires: new Date(Date.now() + 86400 * 1000).toUTCString(),
1863
+ path: "/",
1864
+ });
1865
+ }
1866
+ };
1867
+ FormoAnalyticsSession.prototype.isWalletIdentified = function (address, rdns) {
1868
+ var _a;
1869
+ var identifiedKey = "".concat(address, ":").concat(rdns);
1870
+ var identifiedWallets = ((_a = (0, lib_1.cookie)().get(constants_1.SESSION_WALLET_IDENTIFIED_KEY)) === null || _a === void 0 ? void 0 : _a.split(",")) || [];
1871
+ return identifiedWallets.includes(identifiedKey);
1872
+ };
1873
+ FormoAnalyticsSession.prototype.markWalletIdentified = function (address, rdns) {
1874
+ var _a;
1875
+ var identifiedKey = "".concat(address, ":").concat(rdns);
1876
+ var identifiedWallets = ((_a = (0, lib_1.cookie)().get(constants_1.SESSION_WALLET_IDENTIFIED_KEY)) === null || _a === void 0 ? void 0 : _a.split(",")) || [];
1877
+ if (!identifiedWallets.includes(identifiedKey)) {
1878
+ identifiedWallets.push(identifiedKey);
1879
+ (0, lib_1.cookie)().set(constants_1.SESSION_WALLET_IDENTIFIED_KEY, identifiedWallets.join(","), {
1880
+ // by the end of the day
1881
+ expires: new Date(Date.now() + 86400 * 1000).toUTCString(),
1882
+ path: "/",
1883
+ });
1884
+ }
1727
1885
  };
1728
1886
  return FormoAnalyticsSession;
1729
1887
  }());
@@ -1,5 +1,6 @@
1
1
  export declare const SESSION_TRAFFIC_SOURCE_KEY = "traffic-source";
2
2
  export declare const SESSION_WALLET_DETECTED_KEY = "wallet-detected";
3
+ export declare const SESSION_WALLET_IDENTIFIED_KEY = "wallet-identified";
3
4
  export declare const SESSION_CURRENT_URL_KEY = "analytics-current-url";
4
5
  export declare const SESSION_USER_ID_KEY = "user-id";
5
6
  export declare const LOCAL_ANONYMOUS_ID_KEY = "anonymous-id";
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_PROVIDER_ICON = exports.LOCAL_ANONYMOUS_ID_KEY = exports.SESSION_USER_ID_KEY = exports.SESSION_CURRENT_URL_KEY = exports.SESSION_WALLET_DETECTED_KEY = exports.SESSION_TRAFFIC_SOURCE_KEY = void 0;
3
+ exports.DEFAULT_PROVIDER_ICON = exports.LOCAL_ANONYMOUS_ID_KEY = exports.SESSION_USER_ID_KEY = exports.SESSION_CURRENT_URL_KEY = exports.SESSION_WALLET_IDENTIFIED_KEY = exports.SESSION_WALLET_DETECTED_KEY = exports.SESSION_TRAFFIC_SOURCE_KEY = void 0;
4
4
  exports.SESSION_TRAFFIC_SOURCE_KEY = "traffic-source";
5
5
  exports.SESSION_WALLET_DETECTED_KEY = "wallet-detected";
6
+ exports.SESSION_WALLET_IDENTIFIED_KEY = "wallet-identified";
6
7
  exports.SESSION_CURRENT_URL_KEY = "analytics-current-url";
7
8
  exports.SESSION_USER_ID_KEY = "user-id";
8
9
  exports.LOCAL_ANONYMOUS_ID_KEY = "anonymous-id";
@@ -1,2 +1,2 @@
1
- export declare const version = "1.19.5";
1
+ export declare const version = "1.19.7";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.version = void 0;
4
4
  // Generated by genversion.
5
- exports.version = '1.19.5';
5
+ exports.version = '1.19.7';
6
6
  //# sourceMappingURL=version.js.map
@@ -2,7 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getActionDescriptor = void 0;
4
4
  var getActionDescriptor = function (type, properties) {
5
- return "".concat(type).concat((properties === null || properties === void 0 ? void 0 : properties.status) ? " ".concat(properties === null || properties === void 0 ? void 0 : properties.status) : "");
5
+ var descriptor = type;
6
+ // Add status for events that have it (e.g., signature, transaction)
7
+ if (properties === null || properties === void 0 ? void 0 : properties.status) {
8
+ descriptor += " ".concat(properties.status);
9
+ }
10
+ // Add RDNS for connect/disconnect events to identify the wallet provider
11
+ if ((type === 'connect' || type === 'disconnect') && (properties === null || properties === void 0 ? void 0 : properties.rdns)) {
12
+ descriptor += " (".concat(properties.rdns, ")");
13
+ }
14
+ return descriptor;
6
15
  };
7
16
  exports.getActionDescriptor = getActionDescriptor;
8
17
  //# sourceMappingURL=base.js.map
@@ -22,6 +22,7 @@ export declare class FormoAnalytics implements IFormoAnalytics {
22
22
  */
23
23
  private _trackedProviders;
24
24
  private _injectedProviderDetail?;
25
+ private _processingAccountsChanged;
25
26
  private _seenProviders;
26
27
  config: Config;
27
28
  currentChainId?: ChainID;
@@ -181,6 +182,17 @@ export declare class FormoAnalytics implements IFormoAnalytics {
181
182
  private addProviderListener;
182
183
  private registerAccountsChangedListener;
183
184
  private onAccountsChanged;
185
+ /**
186
+ * Handles changes to the accounts of a given EIP-1193 provider.
187
+ *
188
+ * @param provider - The EIP-1193 provider whose accounts have changed.
189
+ * @param accounts - The new array of account addresses. An empty array indicates a disconnect.
190
+ * @returns A promise that resolves when the account change has been processed.
191
+ *
192
+ * If the accounts array is empty and the provider is the active provider, this method triggers
193
+ * a disconnect flow. Otherwise, it updates the state to reflect the new accounts as needed.
194
+ */
195
+ private _handleAccountsChanged;
184
196
  private registerChainChangedListener;
185
197
  private onChainChanged;
186
198
  private registerConnectListener;
@@ -257,6 +269,11 @@ export declare class FormoAnalytics implements IFormoAnalytics {
257
269
  * @returns The checksummed address or undefined if invalid
258
270
  */
259
271
  private validateAndChecksumAddress;
272
+ /**
273
+ * Helper method to clear the active provider state
274
+ * Centralizes provider clearing logic for consistency
275
+ */
276
+ private clearActiveProvider;
260
277
  /**
261
278
  * Helper method to safely add a provider detail to _providers array, ensuring no duplicates
262
279
  * @param detail The provider detail to add